Java读取InputStream文本的几种方法总结,附读取字节流bytes字节数组byte[]方法

该博客探讨了从InputStream转换为文本的几种方法,包括使用阿里巴巴的Fastjson库、DataInputStream的readUTF方法以及BufferedReader。文章指出,ByteArrayOutputStream是最科学的选择,并提供了详细的代码示例。同时,注意到不同方法存在的潜在问题,如换行符处理和异常处理。
package org.jeecg.common.util;

import com.alibaba.fastjson.util.IOUtils;
import lombok.var;

import java.io.*;

public class StreamUtil {
    /**
     * @deprecated IOUtils.readAll
     */
    static String readText_ali(InputStream inputStream) {
        try {
            InputStreamReader dataReader = new InputStreamReader(inputStream);
            String result = IOUtils.readAll(dataReader);
            dataReader.close();
            inputStream.close();
            return result;
        } catch (Exception ex) {
            LogUtil.debug("Stream2Text error! readText_ali");
            return ex.toString();
        }
    }

    /**
     * @deprecated java.io.EOFException
     */
    static String readText_readUtf(InputStream inputStream) {
        try {
            var dataInputStream = new DataInputStream(inputStream);
            var result = dataInputStream.readUTF();
            dataInputStream.close();
            inputStream.close();
            return result;
        } catch (Exception ex) {
            LogUtil.debug("Stream2Text error! readText_readUtf");
            return ex.toString();
        }
    }

    /**
     * @deprecated 这个是有缺陷的,如果换行符是\n不是\r\n那么文本就变了
     */
    static String readText_bufferedReader(InputStream inputStream) {
        try {
            var inputStreamReader = new InputStreamReader(inputStream);
            var bufferedReader = new BufferedReader(inputStreamReader);
            String line = null;
            StringBuilder stringBuilder = new StringBuilder();
            while ((line = bufferedReader.readLine()) != null)
                stringBuilder.append(line + "\r\n");
            bufferedReader.close();
            inputStreamReader.close();
            inputStream.close();
            return stringBuilder.toString();
        } catch (Exception ex) {
            LogUtil.debug("Stream2Text error! getText_bufferedReader");
            return ex.toString();
        }
    }

    static String readText_bytesOut(InputStream inputStream, String charset) {
        try {
            var byteArrayOutputStream = new ByteArrayOutputStream();
            int _byte;
            while ((_byte = inputStream.read()) != -1)
                byteArrayOutputStream.write(_byte);
            var result = byteArrayOutputStream.toString(charset);
            byteArrayOutputStream.close();
            inputStream.close();
            return result;
        } catch (Exception ex) {
            LogUtil.debug("Stream2Text error! readText_bytesOut");
            return ex.toString();
        }
    }

    public static String readText(InputStream inputStream, String charset) {
        return readText_bytesOut(inputStream, charset);
    }

    public static byte[] readBytes(InputStream inputStream) {
        try {
            var byteArrayOutputStream = new ByteArrayOutputStream();
            int _byte;
            while ((_byte = inputStream.read()) != -1)
                byteArrayOutputStream.write(_byte);
            var result = byteArrayOutputStream.toByteArray();
            byteArrayOutputStream.close();
            inputStream.close();
            return result;
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }
}

总结:ByteArrayOutputStream最科学

<think>我们参考了引用[1]和引用[3]中的内容,将InputStream转换为字节数组的常见方法有以下几种: 1. 使用InputStream的read(byte[])方法循环读取直到流结束(适合任意大小的流,避免一次性读取文件导致内存溢出) 2. 使用Apache Commons IO库中的IOUtils.toByteArray()方法(简洁但需要额外依赖) 3. 对于已知大小的流,可以直接创建对应大小的字节数组(如引用[3]所示,但注意文件大小不能超过整数最大值且必须知道确切大小) 下面提供几种不同的实现方式: 方法一:使用循环读取(推荐,通用且安全) 这是最通用的方法,可以处理任意大小的输入流,通过循环读取避免一次性加载大文件导致内存溢出。 ```java public static byte[] readAllBytes(InputStream inputStream) throws IOException { ByteArrayOutputStream buffer = new ByteArrayOutputStream(); byte[] data = new byte[4096]; // 缓冲区大小,可根据需要调整 int nRead; while ((nRead = inputStream.read(data, 0, data.length)) != -1) { buffer.write(data, 0, nRead); } buffer.flush(); return buffer.toByteArray(); } ``` 方法二:使用Java 9+的InputStream.readAllBytes()(最简单,但要求Java 9+) 如果运行环境是Java 9及以上,可以直接使用InputStream的内置方法: ```java byte[] bytes = inputStream.readAllBytes(); ``` 方法三:使用Apache Commons IO(需要添加依赖) 如果项目中已经使用了Apache Commons IO库,可以使用IOUtils工具类: ```java // 需要添加依赖:commons-io byte[] bytes = IOUtils.toByteArray(inputStream); ``` 方法四:已知流大小(如文件流,且文件大小不超过2GB) 如引用[3]所示,适用于文件流且已知文件大小的情况: ```java public static byte[] readFile(String file) throws IOException { File f = new File(file); // 注意:文件大小不能超过Integer.MAX_VALUE(约2GB) byte[] buffer = new byte[(int) f.length()]; FileInputStream is = new FileInputStream(file); // 注意:read方法可能不会一次性读完,需要检查返回值 int bytesRead = is.read(buffer); if (bytesRead != buffer.length) { throw new IOException("没有完全读取文件"); } is.close(); return buffer; } ``` 但注意,上述方法四不适用于任意输入流(比如网络流可能无法提前知道大小),且必须确保一次读取完成。 推荐使用方法一(循环读取)或方法二(Java 9+)来读取字节数组。 注意事项: 1. 所有方法都需要在读取完毕后关闭流(或者在调用方关闭,或者使用try-with-resources)。 2. 对于大文件,使用方法一(循环读取)并调整缓冲区大小可以平衡内存和性能。 示例:使用循环读取方法方法一)处理网络流 ```java URL url = new URL("https://example.com/image.jpg"); try (InputStream inputStream = url.openStream()) { byte[] bytes = readAllBytes(inputStream); // 使用bytes... } ``` 相关问题: 1. 如何将字节数组转换回InputStream? 2. 在Java中如何高效地处理大文件流(超过内存大小)? 3. 如何将InputStream转换为字符串? 4. 使用BufferedInputStream有什么好处?</think>### Java InputStream 读取字节数组的代码示例 以下是几种InputStream 转换为字节数组的常用方法,适用于不同场景: #### 1. 基础循环读取(推荐通用方案) ```java public static byte[] readAllBytes(InputStream inputStream) throws IOException { ByteArrayOutputStream buffer = new ByteArrayOutputStream(); byte[] data = new byte[4096]; // 缓冲区大小 int bytesRead; while ((bytesRead = inputStream.read(data, 0, data.length)) != -1) { buffer.write(data, 0, bytesRead); } buffer.flush(); return buffer.toByteArray(); } ``` **特点**: - 适用于任意大小的流(自动处理大文件) - 内存效率高(使用固定缓冲区) - Java 7+ 兼容 [^1] #### 2. Java 9+ 内置方法(最简洁) ```java // Java 9+ 专用 byte[] bytes = inputStream.readAllBytes(); ``` **特点**: - 单行代码实现 - 官方内置方法 - 仅限 Java 9+ 环境 #### 3. Apache Commons IO 方案 ```java // 需要依赖:commons-io byte[] bytes = IOUtils.toByteArray(inputStream); ``` **特点**: - 简洁高效 - 需添加库依赖 - 自动处理异常和资源关闭 [^2] #### 4. 文件专用方案(已知文件大小) ```java public static byte[] readFile(File file) throws IOException { try (FileInputStream fis = new FileInputStream(file)) { byte[] buffer = new byte[(int) file.length()]; fis.read(buffer); // 一次性读取 return buffer; } } ``` **限制**: - 仅适用于文件流 - 文件大小需 $\leq 2\text{GB}$(数组长度限制) - 不适用于网络流等未知长度的流 [^3] ### 使用示例 ```java try (InputStream is = new FileInputStream("test.jpg")) { // 方法1:循环读取 byte[] imageData = readAllBytes(is); // PDFBox 图片加载应用 PDImageXObject pdImage = PDImageXObject.createFromByteArray( document, imageData, "image" ); } catch (IOException e) { e.printStackTrace(); } ``` ### 关键注意事项 1. **资源管理**:始终使用 `try-with-resources` 确保流关闭 2. **大文件处理**: - 超过 $2\text{GB}$ 文件必须使用循环读取 - 设置缓冲区大小(建议 $4\text{KB} \sim 64\text{KB}$) 3. **编码问题**: ```java String text = new String(bytes, StandardCharsets.UTF_8); // 字节转字符串 ``` 4. **性能优化**: ```java // 添加缓冲层提升读取效率 try (InputStream bis = new BufferedInputStream(rawStream)) { byte[] data = readAllBytes(bis); } ``` > **内存警告**:处理大文件时,避免一次性读取未知长度的流到内存,可能导致 `OutOfMemoryError`[^1]。
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

上海好程序员

给上海好程序员加个鸡腿!!!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值