任何实用程序 class/method 获取大字符串和 return InputStream?
Any util class/method to take a large String and return an InputStream?
我正在寻找一些实用程序 class/method 来处理大 String
和 return 和 InputStream
.
如果String
很小,我可以这样做:
InputStream is = new ByteArrayInputStream(str.getBytes(<charset>));
但是当String
很大(1MB、10MB或更多)时,当场分配一个字节数组是我的字符串的1到2倍(或更多?)。 (并且由于在完成所有编码之前您不知道要分配多少字节,所以我认为在分配最终字节数组之前必须分配其他 arrays/buffers)。
我有性能需求,想优化这个操作
我认为理想情况下,我正在寻找的 class/method 会在消耗 InputStream 时一次一小块地动态编码字符,因此内存分配不会大幅增加。
看了apache commons的源码IOUtils.toInputStream(..)
,发现它也是把String一次性转成一个大字节数组
并且 StringBufferInputStream
已弃用,并且不能正确完成工作。
哪里有这样的工具class/method?或者我可以只写几行代码来做到这一点?
这个功能的需要是,在其他地方,我使用了一个 util 方法,它接受一个 InputStream
并从这个 InputStream
.
流出字节
我好像没有其他人在寻找这样的东西。我是不是哪里弄错了什么?
我已经开始为此编写自定义 class,但如果有 better/proper/right solution/correction 满足我的需要,我会停止。
对我来说有一个根本性的问题。一开始为什么你的内存中有这么大的 String
s...
总之,你可以试试这个:
public static InputStream largeStringToBytes(final String tooLarge,
final Charset charset)
{
final CharsetEncoder encoder = charset.newEncoder()
.onUnmappableCharacter(CodingErrorAction.REPORT);
final ByteBuffer buf = charset.encode(CharBuffer.wrap(tooLarge));
return new ByteArrayInputStream(buf.array());
}
如果您将大字符串作为参数传递,则内存已分配。一个这么大的字符串甚至不能被压入堆栈(大多数时候最大堆栈大小为 1MB)所以它被分配到堆上只是为了将它作为参数传递。我能看到避免这种情况的唯一方法是在磁盘上创建一棵树,在树上行走时一次流回一个字符。如果您有多个大字符串,也许可以在 Trie 或 DAWG 中为它们编制索引并遍历该结构。这将消除字符串之间的许多重复字符。但是,我需要更多地了解字符串代表什么才能提供进一步帮助。
Java 内置库假定您只需要在输出中从字符转换为字节,而不是输入。 Apache Commons IO 库有 ReaderInputStream,但是,它可以包装一个 StringReader
来得到你想要的。
实现您自己的字符串支持输入流:
class StringifiedInputStream extends InputStream {
private int idx=0;
private final String str;
private final int len;
StringifiedInputStream(String str) {
this.str = str;
this.len = str.length();
}
@Override
public int read() throws IOException {
if(idx>=len)
return -1;
return (byte) str.charAt(idx++);
}
}
这很慢,但它流式传输字节而没有字节数组重复。如果速度有问题,请将 3-arg 方法添加到此实现中。
我正在寻找一些实用程序 class/method 来处理大 String
和 return 和 InputStream
.
如果String
很小,我可以这样做:
InputStream is = new ByteArrayInputStream(str.getBytes(<charset>));
但是当String
很大(1MB、10MB或更多)时,当场分配一个字节数组是我的字符串的1到2倍(或更多?)。 (并且由于在完成所有编码之前您不知道要分配多少字节,所以我认为在分配最终字节数组之前必须分配其他 arrays/buffers)。
我有性能需求,想优化这个操作
我认为理想情况下,我正在寻找的 class/method 会在消耗 InputStream 时一次一小块地动态编码字符,因此内存分配不会大幅增加。
看了apache commons的源码IOUtils.toInputStream(..)
,发现它也是把String一次性转成一个大字节数组
并且 StringBufferInputStream
已弃用,并且不能正确完成工作。
哪里有这样的工具class/method?或者我可以只写几行代码来做到这一点?
这个功能的需要是,在其他地方,我使用了一个 util 方法,它接受一个 InputStream
并从这个 InputStream
.
我好像没有其他人在寻找这样的东西。我是不是哪里弄错了什么?
我已经开始为此编写自定义 class,但如果有 better/proper/right solution/correction 满足我的需要,我会停止。
对我来说有一个根本性的问题。一开始为什么你的内存中有这么大的 String
s...
总之,你可以试试这个:
public static InputStream largeStringToBytes(final String tooLarge,
final Charset charset)
{
final CharsetEncoder encoder = charset.newEncoder()
.onUnmappableCharacter(CodingErrorAction.REPORT);
final ByteBuffer buf = charset.encode(CharBuffer.wrap(tooLarge));
return new ByteArrayInputStream(buf.array());
}
如果您将大字符串作为参数传递,则内存已分配。一个这么大的字符串甚至不能被压入堆栈(大多数时候最大堆栈大小为 1MB)所以它被分配到堆上只是为了将它作为参数传递。我能看到避免这种情况的唯一方法是在磁盘上创建一棵树,在树上行走时一次流回一个字符。如果您有多个大字符串,也许可以在 Trie 或 DAWG 中为它们编制索引并遍历该结构。这将消除字符串之间的许多重复字符。但是,我需要更多地了解字符串代表什么才能提供进一步帮助。
Java 内置库假定您只需要在输出中从字符转换为字节,而不是输入。 Apache Commons IO 库有 ReaderInputStream,但是,它可以包装一个 StringReader
来得到你想要的。
实现您自己的字符串支持输入流:
class StringifiedInputStream extends InputStream {
private int idx=0;
private final String str;
private final int len;
StringifiedInputStream(String str) {
this.str = str;
this.len = str.length();
}
@Override
public int read() throws IOException {
if(idx>=len)
return -1;
return (byte) str.charAt(idx++);
}
}
这很慢,但它流式传输字节而没有字节数组重复。如果速度有问题,请将 3-arg 方法添加到此实现中。