Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/361.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何重构此IO代码?_Java_Coding Style_Io_Nio - Fatal编程技术网

Java 如何重构此IO代码?

Java 如何重构此IO代码?,java,coding-style,io,nio,Java,Coding Style,Io,Nio,我需要从平面文件中读取记录,其中每个128字节构成一个逻辑记录。下面这个读卡器的调用模块只执行以下操作 while(iterator.hasNext()){ iterator.next(); //do Something } 表示每次调用hasNext()后都会有一个next()调用 现在读者来了。 public class FlatFileiteratorReader implements Iterable<String> { FileChannel

我需要从平面文件中读取记录,其中每个128字节构成一个逻辑记录。下面这个读卡器的调用模块只执行以下操作

while(iterator.hasNext()){
    iterator.next();
    //do Something
 }
表示每次调用
hasNext()
后都会有一个
next()
调用

现在读者来了。

public class FlatFileiteratorReader implements Iterable<String> {

    FileChannel fileChannel;

public FlatFileiteratorReader(FileInputStream fileInputStream) {
    fileChannel = fileInputStream.getChannel();
}

private class SampleFileIterator implements Iterator<String> {
    Charset charset = Charset.forName("ISO-8859-1");
    ByteBuffer byteBuffer = MappedByteBuffer.allocateDirect(128 * 100);
    LinkedList<String> recordCollection = new LinkedList<String>();
    String record = null;

    @Override
    public boolean hasNext() {
        if (!recordCollection.isEmpty()) {
            record = recordCollection.poll();
            return true;
        } else {
            try {
                int numberOfBytes = fileChannel.read(byteBuffer);
                if (numberOfBytes > 0) {
                    byteBuffer.rewind();
                    loadRecordsIntoCollection(charset.decode(byteBuffer)
                            .toString().substring(0, numberOfBytes),
                            numberOfBytes);
                    byteBuffer.flip();
                    record = recordCollection.poll();
                    return true;
                }
            } catch (IOException e) {
                // Report Exception. Real exception logging code in place
            }
        }
        try {
            fileChannel.close();
        } catch (IOException e) {
            // TODO Report Exception. Logging
        }
        return false;

    }

    @Override
    public String next() {
        return record;
    }

    @Override
    public void remove() {
        // NOT required

    }

    /**
     * 
     * @param records
     * @param length
     */
    private void loadRecordsIntoCollection(String records, int length) {
        int numberOfRecords = length / 128;
        for (int i = 0; i < numberOfRecords; i++) {
            recordCollection.add(records.substring(i * 128, (i + 1) * 128));
        }
    }

}

    @Override
    public Iterator<String> iterator() {
        return new SampleFileIterator();
    }
}
公共类FlatFileiteratorReader实现Iterable{
文件通道文件通道;
公共FlatFileiteratorReader(FileInputStream FileInputStream){
fileChannel=fileInputStream.getChannel();
}
私有类SampleFileIterator实现迭代器{
Charset Charset=Charset.forName(“ISO-8859-1”);
ByteBuffer ByteBuffer=MappedByteBuffer.allocateDirect(128*100);
LinkedList recordCollection=新建LinkedList();
字符串记录=null;
@凌驾
公共布尔hasNext(){
如果(!recordCollection.isEmpty()){
record=recordCollection.poll();
返回true;
}否则{
试一试{
int numberOfBytes=fileChannel.read(byteBuffer);
如果(numberOfBytes>0){
byteBuffer.rewind();
loadRecordsIntoCollection(字符集解码(byteBuffer))
.toString()子字符串(0,numberOfBytes),
字节数);
byteBuffer.flip();
record=recordCollection.poll();
返回true;
}
}捕获(IOE异常){
//报告异常。实际异常记录代码已就位
}
}
试一试{
fileChannel.close();
}捕获(IOE异常){
//TODO报告异常。日志记录
}
返回false;
}
@凌驾
公共字符串next(){
返回记录;
}
@凌驾
公共空间删除(){
//不需要
}
/**
* 
*@param记录
*@param长度
*/
私有void loadRecordsIntoCollection(字符串记录,整数长度){
int numberOfRecords=长度/128;
for(int i=0;i
该代码在一台硬盘转速为7200 RPM、运行Sun JVM和Windows Xp操作系统的机器上,在1.2秒内读取80 mb的数据。但我对自己编写的代码不太满意。有没有其他更好的方法来写这篇文章(特别是对字符集进行解码并只读取已读取的字节,我指的是
charset.decode(byteBuffer))
.toString().substring(0,numberOfBytes)
部分。请忽略
//TODO
事项)

  • 在这里使用直接缓冲区没有特别的优势。您必须跨JNI边界将数据获取到JavaLand,因此您也可以使用普通的ByteBuffer。直接缓冲区用于在您不想亲自查看数据时复制数据

  • 使用512的倍数的字节缓冲区,例如8192,这样就不会使I/O系统和磁盘控制器疯狂地进行跨扇区边界的读取。在这种情况下,我会考虑使用128*512与您的记录长度一致

  • .substring(0,numberOfBytes)
    是不必要的。读取和倒带后,字节缓冲区的位置为零,其限制值等于
    numberOfBytes
    ,因此charset.decode()操作已经提供了正确的数据量

  • 您假设没有从FileChannel.read()获得短读。您不能假设,Javadoc中没有任何东西支持这种假设。您需要读取,直到缓冲区已满或获得EOF

  • 说到这里,我还将在文件InputStream周围使用BufferedReader和InputStreamReader进行实验,一次只读取128个字符。你可能会惊讶于哪个更快

  • 在这里使用直接缓冲区没有特别的优势。您必须跨JNI边界将数据获取到JavaLand,因此您也可以使用普通的ByteBuffer。直接缓冲区用于在您不想亲自查看数据时复制数据

  • 使用512的倍数的字节缓冲区,例如8192,这样就不会使I/O系统和磁盘控制器疯狂地进行跨扇区边界的读取。在这种情况下,我会考虑使用128*512与您的记录长度一致

  • .substring(0,numberOfBytes)
    是不必要的。读取和倒带后,字节缓冲区的位置为零,其限制值等于
    numberOfBytes
    ,因此charset.decode()操作已经提供了正确的数据量

  • 您假设没有从FileChannel.read()获得短读。您不能假设,Javadoc中没有任何东西支持这种假设。您需要读取,直到缓冲区已满或获得EOF


  • 说到这里,我还将在文件InputStream周围使用BufferedReader和InputStreamReader进行实验,一次只读取128个字符。你可能会惊讶于哪个更快。

    这也许是一个更好的问题。我同意Matt的观点,这应该在codereview上。当你把它贴在那里时,一定要包括你不满意的地方。@mattball我担心我是否会在那里得到更好的答案。如果给我一个选择,我希望问题就在这里。只有一种方法可以找到答案:试试看。除了恐惧本身,没有什么可怕的。还有蜘蛛。这些事情很可怕。这也许是一个更好的问题。我同意马特的观点,这应该放在codereview上。当你把它贴在那里时,一定要包括你不满意的地方。@mattball我担心我是否会在那里得到更好的答案。如果给我一个选择,我希望问题是h