콘솔에서 JavaFX TextArea 로의 출력을위한 UTF-8 인코딩
콘솔의 출력을 JavaFX TextArea로 리디렉션하고 여기에 제안 사항을 따릅니다. JavaFX : SceneBuilder에서 생성 된 TextArea로 콘솔 출력 리디렉션
PrintStream ()에서 charset을 UTF-8로 설정하려고했지만 잘 보이지 않습니다 . charset을 UTF-16으로 설정하면 약간 개선되지만 여전히 읽을 수 없습니다 .
Eclipse IDE에서 콘솔의 예상 텍스트 출력은 정상적으로 나타납니다.
KHA khởi đầu phiên giao dịch sáng nay ở mức 23600 điểm, khối lượng giao dịch trong ngày đạt 765 cổ phiếu, tương đương khoảng 18054000 đồng.
Controller.java
public class Controller {
@FXML
private Button button;
public Button getButton() {
return button;
}
@FXML
private TextArea textArea;
public TextArea getTextArea() {
return textArea;
}
private PrintStream printStream;
public PrintStream getPrintStream() {
return printStream;
}
public void initialize() {
textArea.setWrapText(true);
printStream = new PrintStream(new UITextOutput(textArea), true, StandardCharsets.UTF_8);
} // Encoding set to UTF-8
public class UITextOutput extends OutputStream {
private TextArea text;
public UITextOutput(TextArea text) {
this.text = text;
}
public void appendText(String valueOf) {
Platform.runLater(() -> text.appendText(valueOf));
}
public void write(int b) throws IOException {
appendText(String.valueOf((char) b));
}
}
}
UI.java
public class UI extends Application {
@Override
public void start(Stage stage) {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("Sample.fxml"));
Parent root = loader.load();
Controller control = loader.getController();
stage.setTitle("Title");
stage.setScene(new Scene(root));
stage.show();
control.getButton().setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
try {
System.setOut(control.getPrintStream());
System.setErr(control.getPrintStream());
System.out.println(
"KHA khởi đầu phiên giao dịch sáng nay ở mức 23600 điểm, khối lượng giao dịch trong ngày đạt 765 cổ phiếu, tương đương khoảng 18054000 đồng.");
} catch (Exception e) {
e.printStackTrace();
}
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
Sample.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.layout.BorderPane?>
<BorderPane prefHeight="339.0" prefWidth="468.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/11.0.1" fx:controller="main.Controller">
<center>
<TextArea fx:id="textArea" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER" />
</center>
<right>
<Button fx:id="button" mnemonicParsing="false" onAction="#getButton" text="Button" BorderPane.alignment="CENTER" />
</right>
</BorderPane>
저는 아직 Java를 처음 사용하므로 PrintStream 또는 OutputStream이 정확히 어떻게 작동하는지 잘 알지 못합니다. 나의 무지를 용서해주십시오.
모든 제안에 감사드립니다.
답변
이 코드로 인해 문제가 발생했다고 생각합니다.
public void write(int b) throws IOException {
appendText(String.valueOf((char) b));
}
이것은 각 개별 바이트를 문자로 변환합니다. 즉, 각 문자가 단일 바이트로 표시된다고 가정합니다. 반드시 사실은 아닙니다. UTF-8과 같은 일부 인코딩 은 단일 문자를 나타 내기 위해 여러 바이트를 사용할 수 있습니다. 256 자 이상을 나타낼 수 있어야합니다.
들어오는 바이트를 올바르게 디코딩해야합니다. 직접 시도하는 것보다 .NET과 같은 것을 사용하는 방법을 찾는 것이 좋습니다 BufferedReader
. 운 좋게도 PipedInputStream
및 PipedOutputStream
. 예를 들면 :
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.io.PrintStream;
import java.io.UncheckedIOException;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.stage.Stage;
import static java.nio.charset.StandardCharsets.UTF_8;
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
TextArea area = new TextArea();
area.setWrapText(true);
redirectStandardOut(area);
primaryStage.setScene(new Scene(area, 800, 600));
primaryStage.show();
System.out.println(
"KHA khởi đầu phiên giao dịch sáng nay ở mức 23600 điểm, khối lượng giao dịch trong ngày đạt 765 cổ phiếu, tương đương khoảng 18054000 đồng.");
}
private void redirectStandardOut(TextArea area) {
try {
PipedInputStream in = new PipedInputStream();
System.setOut(new PrintStream(new PipedOutputStream(in), true, UTF_8));
Thread thread = new Thread(new StreamReader(in, area));
thread.setDaemon(true);
thread.start();
} catch (IOException ex) {
throw new UncheckedIOException(ex);
}
}
private static class StreamReader implements Runnable {
private final StringBuilder buffer = new StringBuilder();
private boolean notify = true;
private final BufferedReader reader;
private final TextArea textArea;
StreamReader(InputStream input, TextArea textArea) {
this.reader = new BufferedReader(new InputStreamReader(input, UTF_8));
this.textArea = textArea;
}
@Override
public void run() {
try (reader) {
int charAsInt;
while ((charAsInt = reader.read()) != -1) {
synchronized (buffer) {
buffer.append((char) charAsInt);
if (notify) {
notify = false;
Platform.runLater(this::appendTextToTextArea);
}
}
}
} catch (IOException ex) {
throw new UncheckedIOException(ex);
}
}
private void appendTextToTextArea() {
synchronized (buffer) {
textArea.appendText(buffer.toString());
buffer.delete(0, buffer.length());
notify = true;
}
}
}
}
buffer
위 의 사용은 JavaFX 응용 프로그램 스레드 에 작업 이 넘치지 않도록하기위한 것 입니다.
고려해야 할 몇 가지 다른 사항 :
- 문자열 리터럴을 사용하고 있으므로 소스 파일을 UTF-8로 저장하고 코드를
-encoding UTF-8
. - 와 함께 사용하는 글꼴
TextArea
이 원하는 모든 문자를 나타낼 수 있는지 확인하십시오 . - 그건 가능한 당신은 또한 사용하여 응용 프로그램을 실행해야
-Dfile.encoding=UTF-8
하지만 난 모르겠어요. 나는하지 않았고 여전히 나를 위해 일했습니다.
기본 JVM 인코딩을 UTF-8로 설정하십시오.
java -Dfile.encoding=UTF-8 -jar YourJarfile.jar
자세한 내용은 다음 스레드를 참조하십시오 . 기본 Java 문자 인코딩 설정
파일을 내 보내지 않으려면 Eclipse 환경 설정> 일반> 작업 공간 으로 이동 하여 텍스트 파일 인코딩을 UTF-8 (또는 원하는 인코딩)으로 설정하십시오.
몇 가지 세부 사항이 더 있습니다. Eclipse에서 기본 텍스트 파일 인코딩을 변경하는 방법