在Java中,什么';It’这是最快的方式;“建立”;然后使用字符串,一个字符接一个字符?

在Java中,什么';It’这是最快的方式;“建立”;然后使用字符串,一个字符接一个字符?,java,string,variables,byte,Java,String,Variables,Byte,我有一个间歇接收数据的Java套接字连接。每次突发接收的数据字节数各不相同。数据可以或不可以由已知字符(例如CR或LF)终止。每个数据突发的长度是可变的 我正试图从每次数据突发中构建一个字符串。构建稍后需要解析的字符串的最快方法(速度,而不是内存)是什么 我首先使用字节数组存储传入的字节,然后在每次突发时将它们转换为字符串,如下所示: byte[] message = new byte[1024]; ... message[i] = //byte from socket i++; ... Str

我有一个间歇接收数据的Java套接字连接。每次突发接收的数据字节数各不相同。数据可以或不可以由已知字符(例如CR或LF)终止。每个数据突发的长度是可变的

我正试图从每次数据突发中构建一个字符串。构建稍后需要解析的字符串的最快方法(速度,而不是内存)是什么

我首先使用字节数组存储传入的字节,然后在每次突发时将它们转换为字符串,如下所示:

byte[] message = new byte[1024];
...
message[i] = //byte from socket
i++;
...
String messageStr = new String(message);
...
//parse the string here
这样做的明显缺点是某些突发可能长于1024次。我不想随意创建一个更大的字节数组(如果我的突发更大怎么办?)

这样做的最佳方式是什么?我应该创建一个StringBuilder对象并向其追加()吗?这样我就不必从StringBuilder转换为String(因为前者有我需要的大多数方法)

同样,执行速度是我最关心的问题


TIA.

是你的朋友。根据需要添加尽可能多的字符,然后调用toString()以获取字符串。

请注意,在跨网络层传输时,转换速度可能不是瓶颈。如果你认为这很重要的话,这是值得衡量的

还要注意的是,在从字节到字符串(通过字符)的转换中没有指定字符编码。我会以某种方式强制执行,否则,如果/当您的客户机/服务器在不同的环境中运行时,您的客户机/服务器通信可能会损坏。您可以通过JVM运行时参数强制执行,但这不是一个特别安全的选项

上面给出的,您可能需要考虑预先配置一个合适的大小,这样它就不必重新分配。

< P>我会创建一个“小”字符数组并将其附加到字符中。 当数组已满(或传输结束)时,使用StringBuilder.append(char[]str)方法将数组内容附加到字符串中

现在讨论阵列的“小”尺寸-您需要尝试各种尺寸,看看哪种尺寸最适合您的生产环境(性能“可能”取决于JVM、操作系统、处理器类型和速度等)

编辑:其他人提到过,我同意这也是另一种选择。

您可能希望了解,这取决于您处理的是字节还是字符

我通常会使用ByteArrayOutputStream来组装消息,然后在消息完成时使用toString/toByteArray来检索它


编辑:ByteArrayOutputStream可以通过toString调用处理各种字符集编码。

就个人而言,不依赖于语言,我会将所有字符发送到内存中的数据流,一旦需要字符串,我会将该流中的所有字符读入字符串。 作为替代方案,您可以使用动态数组,在需要添加更多字符时使其更大。更好的是,跟踪实际长度,并使用额外的块(而不是单个字符)增加数组。因此,您可以从1000个字符的数组中的1个字符开始。一旦达到1001,阵列需要调整大小到2000,然后是3000、4000等等

幸运的是,包括Java在内的几种语言都有一个专门处理这个问题的特殊内置类。这些是stringbuilder类。他们使用的任何技术都不是那么重要,但它们是为了提高性能而创建的,因此它们应该是您最快的选择。

看看这门课。它比StringBuilder更快(对于您执行的操作而言),更具确定性


注意:包含该类的项目是针对VM的。不过,它在标准SE/EE环境中完全可用。

首先,您对从客户机收到的字符编码进行了大量假设。它是US-ASCII、ISO-8859-1、UTF-8吗

因为在Java中,字符串不是字节序列,所以在构建可移植字符串序列化代码时,应该明确决定字符编码。因此,您应该永远不要使用StringBuilder将字节转换为字符串。如果您查看StringBuilder界面,您会注意到它甚至没有一个
append(byte)
方法,这并不是因为设计者忽略了它

在您的情况下,您应该明确使用ByteArrayOutputStream。使用ByteArrayOutputStream的直接实现的唯一缺点是其
toByteArray()
方法返回对象内部持有的数组的副本。因此,您可以创建自己的ByteArrayOutputStream子类,并提供对受保护的
buf
成员的直接访问

请注意,如果不使用默认实现,请记住在字符串构造函数中指定字节数组边界。您的代码应该如下所示:

MyByteArrayOutputStream message = new MyByteArrayOutputStream( 1024 );
...
message.write( //byte from socket );
...
String messageStr = new String(message.buf, 0, message.size(), "ISO-8859-1");

ISO-8859-1
替换适合您需要的字符集。

我可能会使用
InputStreamReader
包装在
BufferedInputStream
周围,然后包装套接字。并编写一次处理一条消息的代码,这可能会阻止输入。如果输入是突发的,我可能会在后台线程上运行,并使用并发队列来保存消息

每次读取缓冲区并尝试将其转换为字符正是
BufferedInputStream/InputStreamReader
所做的。它在关注编码的同时做到了这一点,这是(正如其他人所指出的)您的解决方案没有做到的


我不知道为什么您会关注速度,但您会发现处理来自套接字的数据所需的时间远远少于通过该套接字传输数据所需的时间。

为什么执行速度是您的最大目标