我正在通过 Socket 处理 ASCII 输入/输出流,速度至关重要。我听说使用正确的 Java 技术真的很重要。我有一本教科书说使用 Buffers 是最好的方法,但也建议使用 DataInputStreamReader 链接。
对于输出,我使用的是带有 OutputStreamWriter 的 BufferedOutputStream,这似乎很好。但我不确定输入流使用什么。我正在开发新产品线,那么 Scanner 会有用吗?速度至关重要,我需要尽快将数据从网络中取出。
谢谢。
酸碱度
我正在通过 Socket 处理 ASCII 输入/输出流,速度至关重要。我听说使用正确的 Java 技术真的很重要。我有一本教科书说使用 Buffers 是最好的方法,但也建议使用 DataInputStreamReader 链接。
对于输出,我使用的是带有 OutputStreamWriter 的 BufferedOutputStream,这似乎很好。但我不确定输入流使用什么。我正在开发新产品线,那么 Scanner 会有用吗?速度至关重要,我需要尽快将数据从网络中取出。
谢谢。
酸碱度
只为一笑...
socket = new ServerSocket(2004, 10);
connection = socket.accept();
in = connection.getInputStream();
InputStreamReader isr = new InputStreamReader(in);
BufferedReader br = new BufferedReader(isr);
String line = null;
do {
line = br.readLine();
} while (!"done".equals(line));
使用LOOPBACK,即在我的机器上使用本地进程运行到本地主机,并使用适当的“愚蠢”客户端。
requestSocket = new Socket("localhost", 2004);
out = requestSocket.getOutputStream();
PrintWriter pw = new PrintWriter(out);
String line = "...1000 characters long...";
for (int i = 0; i < 2000000 - 1; i++) {
pw.println(line);
}
line = "done";
pw.println(line);
pw.flush();
您会注意到这会发送 2M “1000 char” 行。这只是一个粗略的吞吐量测试。
在我的机器上,环回传输速率约为 190MB/秒。字节,而不是位。190,000 行/秒。
我的观点是,使用骨干 Java 套接字的“简单”方式非常快。这将使任何常见的网络连接饱和(这意味着网络将比您的 I/O 更慢地减慢您的速度)。
可能“足够快”。
你期待什么样的流量?
如果速度绝对关键,请考虑使用 NIO。这是针对完全相同的问题发布的代码示例。
http://lists.apple.com/archives/java-dev/2004/Apr/msg00051.html
编辑:这是另一个例子
http://www.java2s.com/Code/Java/File-Input-Output/UseNIOtoreadatextfile.htm
编辑 2:我写了这个微基准来让你开始测量各种方法的性能。一些人评论说 NIO 不会执行得更快,因为你需要做更多的工作来将数据“按摩”成可用的形式,所以你可以根据你想要做的任何事情来验证它。当我在我的机器上运行这段代码时,NIO 代码在 45 兆字节的文件中快了大约 3 倍,在 100 兆字节的文件中快了 5 倍。
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.Scanner;
public class TestStuff {
public static void main(final String[] args)
throws IOException, InterruptedException {
final String file_path = "c:\\test-nio.txt";
readFileUsingNIO(file_path);
readFileUsingScanner(file_path);
}
private static void readFileUsingScanner(final String path_to_file)
throws FileNotFoundException {
Scanner s = null;
final StringBuilder builder = new StringBuilder();
try {
System.out.println("Starting to read the file using SCANNER");
final long start_time = System.currentTimeMillis();
s = new Scanner(new BufferedReader(new FileReader(path_to_file)));
while (s.hasNext()) {
builder.append(s.next());
}
System.out.println("Finished! Read took " + (System.currentTimeMillis() - start_time) + " ms");
}
finally {
if (s != null) {
s.close();
}
}
}
private static void readFileUsingNIO(final String path_to_file)
throws IOException {
FileInputStream fIn = null;
FileChannel fChan = null;
long fSize;
ByteBuffer mBuf;
final StringBuilder builder = new StringBuilder();
try {
System.out.println("Starting to read the file using NIO");
final long start_time = System.currentTimeMillis();
fIn = new FileInputStream("c:\\test-nio.txt");
fChan = fIn.getChannel();
fSize = fChan.size();
mBuf = ByteBuffer.allocate((int) fSize);
fChan.read(mBuf);
mBuf.rewind();
for (int i = 0; i < fSize; i++) {
//System.out.print((char) mBuf.get());
builder.append((char) mBuf.get());
}
fChan.close();
fIn.close();
System.out.println("Finished! Read took " + (System.currentTimeMillis() - start_time) + " ms");
}
catch (final IOException exc) {
System.out.println(exc);
System.exit(1);
}
finally {
if (fChan != null) {
fChan.close();
}
if (fIn != null) {
fIn.close();
}
}
}
AScanner用于分隔文本。你没有谈论你的数据是什么样的,所以我不能对此发表评论。
如果您只想阅读每个换行符,请使用
BufferedReader r = new BufferedReader(new InputStreamReader(Socket.getInputStream()))
和
r.readLine()
当你得到一个空值时,你会知道你已经用尽了流中的数据。
就速度而言,它们都只是从流中读取数据。因此,假设您不需要 a 的额外功能Scanner,我看不出有什么特别的理由使用它。
我会用 BufferedReader 做一些事情:
Collection<String> lines = new ArrayList<String>();
BufferedReader reader = new BufferedReader( new InputStreamReader( Foo.getInputStream()));
while(reader.ready())
{
lines.add( reader.readLine());
}
myClass.processData(lines); //Process the data after it is off the network.
根据您的情况,您可以有一个额外的线程来处理“行”中的项目,因为它正在被填充,但是您需要使用不同的结构来支持集合 - 一个可以同时使用的结构。