Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/360.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 缓冲区的安全实现_Java_Security_Io_Bufferedreader - Fatal编程技术网

Java 缓冲区的安全实现

Java 缓冲区的安全实现,java,security,io,bufferedreader,Java,Security,Io,Bufferedreader,我想使用BufferedReader读取上载到服务器的文件 该文件将被写入CSV文件,但我不能假设这一点,因此我编写了一些测试,其中该文件是图像或二进制文件(假设客户端向我发送了错误的文件或攻击者试图破坏我的服务),或者更糟糕的是,该文件是有效的CSV文件,但有一行100MB 我的应用程序可以处理此问题,但它必须读取文件的第一行: ... String firstLine = bufferedReader.readLine(); //Perform some validations and re

我想使用BufferedReader读取上载到服务器的文件

该文件将被写入CSV文件,但我不能假设这一点,因此我编写了一些测试,其中该文件是图像或二进制文件(假设客户端向我发送了错误的文件或攻击者试图破坏我的服务),或者更糟糕的是,该文件是有效的CSV文件,但有一行100MB

我的应用程序可以处理此问题,但它必须读取文件的第一行:

...
String firstLine = bufferedReader.readLine();
//Perform some validations and reject the file if it's not a CSV file
...
但是,当我编写一些测试代码时,我发现了一个潜在的风险:BufferedReader在找到返回行之前不会对读取的字节数执行任何控制,因此它可能最终抛出OutOfMemoryError

这是我的测试:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import org.junit.Test;

public class BufferedReaderTest {

    @Test(expected=OutOfMemoryError.class)
    public void testReadFileWithoutReturnLineCharacter() throws IOException {
        BufferedReader bf = new BufferedReader(getInfiniteReader());

        bf.readLine();

        bf.close();
    }

    private Reader getInfiniteReader() {
        return new Reader(){

            @Override
            public int read(char[] cbuf, int off, int len) throws IOException {
                return 'A';
            }

            @Override
            public void close() throws IOException {

            }
        };
    }
}
我一直在互联网上寻找一些安全的BufferedReader实现,但什么也找不到。我找到的唯一类是来自ApacheIO的
BoundedInputStream
,它限制了输入流读取的字节数

我需要一个BufferedReader的实现,它知道如何限制每行中读取的字节/字符数

大概是这样的:

  • 该应用程序调用“readLine()”
  • BufferedReader读取字节,直到找到返回行字符或达到允许的最大字节数
  • 如果它找到了返回行字符,则重置读取的字节(以便它可以读取下一行)并返回内容
  • 如果已达到允许的最大字节数,则抛出异常

有人知道BufferedReader的实现具有这种行为吗?

这不是检测文件是否为二进制文件的方法

下面是如何检查文件是否为真正的文本;请注意,这要求您事先知道编码:

final Charset cs = StandardCharsets.UTF_8; // or another

final CharsetDecoder decoder = cs.newDecoder()
    .onMalformedInput(CodingErrorAction.REPORT); // default is REPLACE!

// Here, "in" is the input stream from the file
try (
    final Reader reader = new InputStreamReader(in, decoder);
) {
    final char[] buf = new char[4096]; // or other size
    while (reader.read(buf) != -1)
        ; // nothing
} catch (MalformedInputException e) {
    // cannot decode; binary, or wrong encoding
}
现在,由于可以通过
读取器
初始化
缓冲读取器
,因此可以使用:

try (
    final Reader r = new InputStreamReader(in, decoder);
    final BufferedReader reader = new BufferedReader(r);
) {
    // Read lines normally
} catch (CharacterCodingException e) {
    // Not a CSV, it seems
}

// etc

现在,再解释一下这是如何工作的。。。虽然这是阅读Java文本的基本部分,但它也是一个同样被误解的部分

当您使用
读取器
以文本形式读取文件时,必须指定字符编码;在Java中,这是一个
字符集

内部情况是Java将从该
字符集
创建
字符集解码器
,读取
字节
流并输出
字符
流。处理错误的方法有三种:

  • CodingErrorAction.REPLACE
    默认值)):不可映射的字节序列被替换为(它确实响了,对吧?)
  • CodingErrorAction.IGNORE
    :不可映射的字节序列不会触发
    字符的发射
    
  • CodingErrorAction.REPORT
    :不可映射的字节序列触发要抛出的
    CharacterCodingException
    ,该异常继承了
    IOException
    ;反过来,
    CharacterCodingException
    的两个子类是
    格式错误的putException
    不可映射的characterexception
因此,要检测文件是否为真正的文本,您需要做的是:

  • 事先知道编码
  • 使用配置了
    CodingErrorAction.REPORT
    CharsetDecoder
  • InputStreamReader
    中使用它
这是一种方式;还有其他的。然而,它们都会在某个时候使用
CharsetDecoder


类似地,对于反向操作(
char
stream to
byte
stream),也有一个
CharsetEncoder
),这就是
Writer
家族所使用的。

谢谢@fge的回答。我最终实现了一个安全的
阅读器
,它可以处理行太长(或者根本没有行)的文件

如果有人想查看代码,可以在此处查看该项目(即使有许多测试,也非常小的项目):


等等,为什么要用
读取器
读取二进制数据?你说你可以在“图像和二进制文件”之间进行“选择”…对不起,我会尝试改进我的问题。我使用的是
阅读器
,因为我的服务设计为只处理CSV文件。但我必须处理客户端向我发送二进制文件的情况(不管是否意外)。在这种情况下,我的服务可以拒绝该文件,但它需要读取第一行。好的,那么我已取消删除我的答案。基本上,您不需要“读取第一行”:只需适当配置
读取器
,并在其上使用
缓冲读取器
。更多细节请参见我的答案。这似乎根本没有解决问题。OP正在寻找一个实现,引用:“读取字节直到它[…]或者它达到允许的最大字节数”@Unihedro引用这样一个问题:“该文件将被写入CSV文件,但我不能假设这一点”这可能解决二进制文件的问题,但是如果该文件有一行100MB的字符,会发生什么?请看我的JUnit测试。它返回有效字符,但数量无限them@jfcorugedo如果您真的想这样做,那么不要使用
BufferedReader
;使用一个简单的
读取器
,一个字符数组缓冲区,并在阅读时附加到
StringBuilder
。好的。我知道我可以编写一个解决方案,但我想使用一个经过良好验证的实现(Apache?),但我找不到任何东西。但是,非常感谢,我不知道
编码错误操作