Java 如何正确解码和编码JTextArea中的字符
我有一个在控制台上运行的程序,我想为它制作一个自定义控制台。当前的命令行界面可以用一个以InputStream和PrintStream为参数的方法启动 我有两个文本区域(JTextArea),一个用于输入,另一个用于输出。我扩展了InputStream和OutputStreams,为我的启动方法提供了流:Java 如何正确解码和编码JTextArea中的字符,java,swing,encoding,stream,Java,Swing,Encoding,Stream,我有一个在控制台上运行的程序,我想为它制作一个自定义控制台。当前的命令行界面可以用一个以InputStream和PrintStream为参数的方法启动 我有两个文本区域(JTextArea),一个用于输入,另一个用于输出。我扩展了InputStream和OutputStreams,为我的启动方法提供了流: public class ConsoleInputStream extends InputStream implements KeyListener { private Bl
public class ConsoleInputStream extends InputStream implements KeyListener {
private BlockingDeque<Integer> mBuffer = new LinkedBlockingDeque<>();
private JTextArea mJTextArea;
public ConsoleInputStream(JTextArea JTextArea) {
mJTextArea = JTextArea;
mJTextArea.addKeyListener(this);
}
@Override
public void keyTyped(KeyEvent e) {}
@Override
public void keyPressed(KeyEvent e) {}
@Override
public void keyReleased(KeyEvent e) {
int key = e.getKeyChar();
char c = (char) key;
mBuffer.add(key);
}
@Override
public int read() {
try {
char c = (char) (int) mBuffer.take();
if(c == '\n')
mJTextArea.setText("");
return c;
} catch (InterruptedException e) {
e.printStackTrace();
}
return 0;
}
@Override
public int read(byte[] b, int off, int len) {
if (b == null) {
throw new NullPointerException();
} else if (off < 0 || len < 0 || len > b.length - off) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return 0;
}
int c = read();
if (c == -1) {
return -1;
}
b[off] = (byte)c;
int i = 1;
try {
for (; i < len && available() > 0 ; i++) {
c = read();
if (c == -1) {
break;
}
b[off + i] = (byte)c;
}
} catch (IOException e) {
}
return i;
}
}
启动程序:
CommandInterface.get().start(ui.getConsoleIn(), new PrintStream(ui.getConsoleOut()));
(ui是扩展JFrame的类的实例,getConsoleIn()和getConsoleOut()返回ConsoleInputStream和ConsoleOutput Stream的实例)
其中我使用扫描仪读取输入流:
public void start(InputStream inputStream, PrintStream outputStream){
Scanner scanner = new Scanner(inputStream, "UTF-8");
while (true){
String[] input = scanner.nextLine().split(" ");
if(input[0].equals("exit"))
break;
Command command = mCommands.get(input[0]);
if(command == null){
displayErrorMessage("No such command", outputStream);
continue;
}
List<String> flags = new LinkedList<>();
List<String> params = new LinkedList<>();
for(String s : Arrays.copyOfRange(input, 1, input.length)){
if(s.charAt(0) == '/')
flags.add(s.substring(1));
else
params.add(s);
}
command.execute(outputStream, flags, params);
}
}
使用不同的字符集,但无法使它们正确显示
显示这些(以及其他UTF-8)字符的正确方式是什么?我不确定您是否犯了其他错误,但我知道您至少需要解决这个问题:
read
和write
方法不处理字符,而是处理字节。一个字符!=一个字节
我说的是:
public int read() {
try {
char c = (char) (int) mBuffer.take();
if(c == '\n')
mJTextArea.setText("");
return c;
} catch (InterruptedException e) {
e.printStackTrace();
}
return 0;
}
public void write(int b) throws IOException {
mJTextArea.append(String.valueOf((char) b));
}
您需要使用扫描仪可以理解的编码将字符
转换为字节
数组。然后将每个字节转换为无符号整数,而不是将每个字符视为单个字节
public void keyReleased(KeyEvent e) {
int key = e.getKeyChar();
char c = (char) key;
if(c == '\n')
mJTextArea.setText("");
byte[] byteArray = Character.toString(c).getBytes(StandardCharset.UTF_8);
for (byte b : byteArray) {
mBuffer.add(Byte.toUnsignedInt(b));
}
}
public int read() {
try {
byte b = (int) mBuffer.take();
return b;
} catch (InterruptedException e) {
e.printStackTrace();
}
return -1;
}
对于write
,也不能将每个字节视为单个字符。处理此问题的一种方法是直接将PrintStream
子类化。有关示例,请参见中的解决方案2 我需要做的事情是忽略未定义的字符(有些键如ALT或CTRL没有与之关联的字符,因此结果是char 65535-char undefined-)
当您尝试使用“śćóżźetc”时,实际发生了什么?当我使用UTF-8直接打印它们(来自上一个代码示例)时,输出是:ᅤロ ᅣヌ ᅢᄈ ᅤᄐ ᅤᄎ etcDoes
CommandInterface.get().start
接受InputStream
和PrintStream
?ui.getConsoleIn()是否返回ConsoleInputStream
?以及新扫描仪(InputStream,“UTF-8”)
与所有这些有什么关系?是的,CommandInterface.get().start是启动我在开头提到的命令行界面的方法。ui.getConsoleIn()返回一个ConsoleInputStream。扫描器用于读取输入(命令),执行后,输出写入传递给CommandInterface.get()的打印流.start方法。抱歉,缺少详细信息,我将为问题添加更多代码
public int read() {
try {
char c = (char) (int) mBuffer.take();
if(c == '\n')
mJTextArea.setText("");
return c;
} catch (InterruptedException e) {
e.printStackTrace();
}
return 0;
}
public void write(int b) throws IOException {
mJTextArea.append(String.valueOf((char) b));
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyChar();
char c = (char) key;
if(c == '\n')
mJTextArea.setText("");
byte[] byteArray = Character.toString(c).getBytes(StandardCharset.UTF_8);
for (byte b : byteArray) {
mBuffer.add(Byte.toUnsignedInt(b));
}
}
public int read() {
try {
byte b = (int) mBuffer.take();
return b;
} catch (InterruptedException e) {
e.printStackTrace();
}
return -1;
}
@Override
public void keyReleased(KeyEvent e) {
char c = e.getKeyChar();
if(c == '\n')
mJTextArea.setText("");
if(c == KeyEvent.CHAR_UNDEFINED)
return;
byte[] byteArray = Character.toString(c).getBytes(StandardCharsets.UTF_8);
for (byte b : byteArray) {
mBuffer.add(Byte.toUnsignedInt(b));
}
}