1

我正在通过 Socket 处理 ASCII 输入/输出流,速度至关重要。我听说使用正确的 Java 技术真的很重要。我有一本教科书说使用 Buffers 是最好的方法,但也建议使用 DataInputStreamReader 链接。

对于输出,我使用的是带有 OutputStreamWriter 的 BufferedOutputStream,这似乎很好。但我不确定输入流使用什么。我正在开发新产品线,那么 Scanner 会有用吗?速度至关重要,我需要尽快将数据从网络中取出。

谢谢。

酸碱度

4

4 回答 4

3

只为一笑...

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 更慢地减慢您的速度)。

可能“足够快”。

你期待什么样的流量?

于 2010-01-22T02:01:59.700 回答
1

如果速度绝对关键,请考虑使用 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();
            }
        }

    }
于 2010-01-21T18:56:35.207 回答
0

AScanner用于分隔文本。你没有谈论你的数据是什么样的,所以我不能对此发表评论。

如果您只想阅读每个换行符,请使用

BufferedReader r = new BufferedReader(new InputStreamReader(Socket.getInputStream()))

r.readLine()

当你得到一个空值时,你会知道你已经用尽了流中的数据。

就速度而言,它们都只是从流中读取数据。因此,假设您不需要 a 的额外功能Scanner,我看不出有什么特别的理由使用它。

于 2010-01-21T18:33:07.253 回答
-1

我会用 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.

根据您的情况,您可以有一个额外的线程来处理“行”中的项目,因为它正在被填充,但是您需要使用不同的结构来支持集合 - 一个可以同时使用的结构。

于 2010-01-21T18:46:10.433 回答