六种不同'?' ASCII中的字符?

时间:2014-06-13 15:53:02

标签: java serial-port arduino ascii

我写了一个读取GameBoy推车的Arduino程序,Java发送一个字符开始,它开始读取并发回字节。在十六进制编辑器(甚至文本编辑器)中打开转储的rom,乍一看显示它们是相同的,在编辑器中使用compare函数后,它突出显示转储rom中的所有0x3F字符都是错误的 - 只有它们。 我的Arduino程序的每个功能在执行此操作之前都已经过测试,因此我唯一能想到的就是测试Java端。 为了测试这个,我简单地制作了另一个简单的Arduino程序,它在其十进制数字旁边的串行发送每个ascii字符(0-255)。我意识到事实上有六种不同的表现形式?字符,这是文件的那些部分:

59: ;
60: <
61: =
62: >
63: ? <
64: @
65: A
66: B
...
125: }
126: ~
127: 
128: €
129: ? <
130: ‚
131: ƒ
132: „
...
140: Œ
141: ? <
142: Ž
143: ? <
144: ? <
145: ‘
146: ’
147: “
...
154: š
155: ›
156: œ
157: ? <
158: ž
159: Ÿ
160:  

以下是有问题的Java代码:

final Arduino board = new Arduino("COM5", 115200);
BufferedWriter rom = new BufferedWriter(new FileWriter("[ROM].gb"));
board.write((byte)0);
Thread.sleep(10000);
while (board.hasavailable() > 0) {
    String data = new String(board.read(board.hasavailable()));
    rom.write(data);
    Thread.sleep(1000);
}
rom.flush();
rom.close();

我无法看到这是一个通信问题,好像波特率是错误的,这将是垃圾,如果这是一个像UTF-8到ASCII的文本格式问题,肯定会是这样的... 基本上Java必须与&#39;?&#39;混淆。角色,并始终假设它是第一个实例。在将byte []转换为字符串时,我是否遗漏了一些东西,因为看起来这是一个明显的问题,就像我一样。

编辑1:

我一直在使用asciitable.com作为让所有角色都一致的依据。

我还发现,如果我将文件编写代码更改为:

byte[] data = board.read(readsize);
for (byte in : data)
    rom.write(in);

所有扩展集(128+)都变成了&#39;?&#39; s。这可能是bufferedWriter的一个问题吗?

编辑2:可重复的示例

这是我正在使用的Arduino和Java代码。

http://pastebin.com/Tijjdb0A

在Java编写文件后,在十六进制编辑器中检查它,并看到上面提到的字符都已更改为0x3F。

3 个答案:

答案 0 :(得分:0)

我认为问题在于您将原始数据从字节转换为String,然后只将字符串写入缓冲的writer。根据文档

,当您致电new String(byte[])
Constructs a new String by decoding the specified array of bytes using the platform's default charset.

这意味着它占用你的字节,假设它是你机器上默认字符集的字符串,然后将其转换为UTF-16,这是Java中字符串的内部表示。在许多平台上,“默认字符集”表示UTF-8,而在UTF-8中,“扩展ASCII”的大多数字节,即128和更高字节,是较长字符的一部分,占用多于一个字节。您的字节可能不是有效的UTF-8字符串,因此某些字符会被破坏。

我认为如果您直接将字节写入文件,而不是首先使用字符串,即使用BufferedOutputStream(FileOutputStream),而不是BufferedWriter(FileWriter),一切都会好的。

答案 1 :(得分:0)

“每个ascii字符(0-255)”:至少你不了解ASCII是什么。但你不应该这样做;它已经过时了。 €,...,Ÿ,...不是ASCII。

如果要将任意字节视为字符,每个字符一个字节,则需要一个至少包含256个字符的字符集,并且编码使用0-255作为单字节字符。试试CP437。 Java处理得很好。请看OutputStreamWriter

答案 2 :(得分:0)

我很高兴你对提供的其他答案感到满意。只是为了澄清问题标题所带来的误解:

  

六种不同'?' ASCII中的字符?

不,ASCII中的问号不超过一个。 ASCII仅将字符分配给值0到127,并且只有其中一个(十进制63)是问号。 ASCII有许多“扩展”,它们将字符分配给位置为128到255的位置,但即使这样,某些值也可能未被分配。

您在输出中看到的五个额外问号对应于Windows-1252中的未分配位置。 Windows-1252是Microsoft Windows的(北美版)中的默认字符集,因此当您使用Reader或Writer类或String构造函数时,它会发挥作用,而不指定字符集。

当Java将字节转换为字符(反之亦然)并遇到“格式错误的输入或不可映射的字符序列”时,它会使用问号作为替换字符。这在Charset Javadoc中暗示过,但在那里没有得到很好的解释。