汉中网站开发,对网站建设心得,网页图片另存为的时候保存不了jpg,上海文化传媒公司排名一、字节流读写单位#xff1a;字节 (byte)#xff0c;即 8 位二进制数。读取方式#xff1a;它不管你读的是什么文件#xff08;是图片、视频还是文本#xff09;#xff0c;它都把内容当成一串原始的二进制数据来搬运。你的代码#xff1a;inputStream.read(bytes) 读…一、字节流读写单位字节 (byte)即 8 位二进制数。读取方式它不管你读的是什么文件是图片、视频还是文本它都把内容当成一串原始的二进制数据来搬运。你的代码inputStream.read(bytes)读取的就是纯粹的字节。如果你用System.out.printf(0x%02X, bytes[i])打印看到的是内存中的真实二进制数据。适用所有类型的文件万能。使用 Java 字节流读取任何二进制数据法一public class Demo7_1 { public static void main(String[] args) throws IOException { //选择合适的 InputStream 子类如 FileInputStream并指定数据源。 InputStream inputStream new FileInputStream(./1.txt); //循环读取数据 while(true) { int data inputStream.read(); if(data -1) { break; } //以 16 进制格式化打印读取数据 System.out.printf(0x%X\n,data); } 关闭流释放资源 inputStream.close(); } }以上代码就实现了从 1.txt 文件中读取字节数据的功能我们来刨析一下:1、为什么要 使用 InputStream inputStream new FileInputStream(./1.txt);“左边写父类或接口右边写具体的实现类” —— 这是写出高质量、可扩展 Java 代码的基本功。1、语法层面向上转型Upcasting选择合适的 InputStream 子类如 FileInputStream并指定数据源。 InputStream inputStream new FileInputStream(./1.txt); 是一种典型的 “父类引用指向子类对象” 的写法体现了 Java 中 多态Polymorphism 和 面向抽象编程 的核心思想FileInputStream是InputStream的子类。将子类对象赋值给父类类型的变量称为 向上转型。这在 Java 中是自动且安全的不需要强制类型转换。// 向上转型隐式 InputStream inputStream new FileInputStream(...); // ✅ 合法 // 向下转型需显式强转且有风险 FileInputStream fis (FileInputStream) inputStream; // ⚠️ 需确保类型匹配2、设计层面面向接口/抽象类编程虽然InputStream是一个 抽象类不是接口但它扮演了“通用输入流”的角色。这种写法的好处是代码更通用、灵活你后续调用的方法如read()、close()都是通过InputStream定义的通用接口进行的。这意味着将来可以轻松替换数据源而无需修改使用逻辑。// 今天读文件 InputStream in new FileInputStream(data.txt); // 明天读网络 InputStream in new SocketInputStream(socket); // 后天读内存 InputStream in new ByteArrayInputStream(bytes);→ 只要右边换一个InputStream的实现类左边和后续代码完全不用动解耦与可维护性高你的业务逻辑只依赖于“能读字节”这个能力InputStream抽象而不关心底层是文件、网络还是内存。这符合 “依赖倒置原则”DIP。便于组合与装饰Decorator 模式Java I/O 流大量使用装饰器模式这种写法天然支持InputStream in new BufferedInputStream( new FileInputStream(large.txt) );这里BufferedInputStream包装了FileInputStream但对外仍表现为InputStream使用方式不变2、int data inputStream.read();是 Java 字节流InputStream中最基础、最核心的单字节读取操作。它的作用是从输入流中读取下一个字节的数据并以int类型返回。1、返回值含义⚠️ 注意虽然读的是byte有符号-128~127但返回int是为了能用-1表示结束同时避免负数字节如0xFF -1与结束标志混淆。2为什么返回int而不是byte如果返回byte那么当读到字节值为-1即0xFF时程序无法区分这是“有效数据”还是“流结束”。使用int后有效字节被提升为0~255的正整数-1专用于表示“结束”无歧义。3、关闭字节流inputStream.close();是 Java I/O 操作中释放系统资源的关键一步。它的作用是关闭输入流并释放与该流关联的所有底层系统资源如文件句柄、网络连接、内存缓冲区等。为什么必须调用close()防止资源泄漏Resource Leak每打开一个文件操作系统会分配一个 文件描述符File Descriptor。如果不关闭流这些描述符会一直被占用直到程序退出。操作系统对单个进程能打开的文件数有限制如 Linux 默认 1024资源耗尽会导致程序崩溃抛出IOException: Too many open files。确保数据完整性对输出流更重要虽然InputStream主要是读取但某些流如带缓冲的BufferedInputStream可能在内部维护状态及时关闭有助于清理。符合“谁打开谁关闭”原则良好的编程习惯打开资源后必须显式或隐式地关闭它。法二public class Demo7_2 { public static void main(String[] args) throws IOException { InputStream inputStream new FileInputStream(./1.txt); //通过 read 读取数据一次就读一个字节数组 while(true) { //长度随便定无所谓 byte[] bytes new byte[1024]; //read 方法会尽可能的把参数的数组填满 //返回值表示实际读取到的字节数 int n inputStream.read(bytes); if(n -1) { break; } for (int i 0; i n; i) { System.out.printf(0x%X\n,bytes[i]); } } //若上面代码出现异常close() 可能执行不到 inputStream.close(); } }法二与法一的区别是这使用字节流逐块读取文件并以十六进制形式打印每个字节4、int n inputStream.read(bytes);是 Java 字节流InputStream中“批量读取”数据的标准写法属于 I/O 编程中最核心、最常用的模式之一。参数byte[] b—— 一个字节数组作为缓冲区buffer用于接收读取到的数据。返回值int—— 表示实际读取到的字节数不是数组长度。✅ 所以int n inputStream.read(bytes);的意思是“尝试从输入流中读取最多bytes.length个字节存入bytes数组并把实际读到的字节数赋给变量n。”✅ 具体过程以文件大小 1024 字节为例假设文件总长度为2500 字节你使用byte[1024]缓冲区循环次数调用read(bytes)后实际返回值n读取的字节范围流内部指针位置第 1 次读取前 1024 字节n 1024字节 0 ~ 1023指向第1024字节即下一次从 1024 开始第 2 次读取接下来的 1024 字节n 1024字节 1024 ~ 2047指向第2048字节第 3 次读取剩余 452 字节n 452字节 2048 ~ 2499指向文件末尾EOF第 4 次尝试再读n -1无数据已到末尾返回 -1法三public class Demo7_3 { public static void main(String[] args) throws IOException { InputStream inputStream null; try { inputStream new FileInputStream(./1.txt); //通过 read 读取数据一次就读一个字节数组 while(true) { //长度随便定无所谓 byte[] bytes new byte[1024]; //read 方法会尽可能的把参数的数组填满 //返回值表示实际读取到的字节数 int n inputStream.read(bytes); if(n -1) { break; } for (int i 0; i n; i) { System.out.printf(0x%X\n,bytes[i]); } } } finally { //关闭文件 inputStream.close(); } } }法三保证了inputStream.close()被执行5、保证inputStream.close()被执行在法二中虽然方法声明了throws IOException但read()或printf()在循环中仍可能抛出异常。一旦异常抛出程序会直接跳转到调用栈上层跳过close()语句。结果文件句柄未释放 → 资源泄漏Resource Leak。法四public class Demo8 { // try with resource public static void main(String[] args) { try(InputStream inputStream new FileInputStream(./1.txt)) { while(true) { byte[] bytes new byte[1024]; int n inputStream.read(bytes); if(n -1) { break; } for (int i 0; i n; i) { System.out.printf(0x%X\n,bytes[i]); } } // close 不必写了 //会在 try 结束的时候自动调用 close() }catch (IOException e) { e.printStackTrace(); } } }6、使用try-with-resources确保资源释放try-with-resources是 Java 7 引入的一种自动资源管理Automatic Resource Management, ARM 语法用于确保每个打开的资源在使用完毕后都能被正确关闭即使发生异常也不会泄漏资源。“任何实现了Closeable/AutoCloseable的资源都必须用try-with-resources管理✅ 基本语法try (ResourceType resource new ResourceType(...)) { // 使用 resource 的代码 } catch (ExceptionType e) { // 处理异常 } // resource 在此处自动关闭无论是否抛出异常前提资源类必须实现java.lang.AutoCloseable接口Closeable是其子接口。Java I/O 中的所有流如FileInputStream、FileReader都实现了该接口。7、3 种read方法1、int read()读取单个字节8 位。返回该字节的 无符号整数值0 ~ 255。如果已到达流末尾EOF返回-1。2、int read(byte[] b)尝试读取 最多b.length个字节 到数组b中。返回 实际读取的字节数0 ≤ n ≤ b.length。如果已到流末尾返回-1。3.int read(byte[] b, int off, int len)从输入流中读取 最多len个字节存入数组b的 从索引off开始的位置。返回 实际读取的字节数。流结束时返回-1。使用 Java 字节流写任何二进制数据法一public class Demo9_1 { public static void main(String[] args) { //如果没有 true 会把原来的内容清空再写 try(OutputStream outputStream new FileOutputStream(./1.txt)) { // 97 十进制表示 a outputStream.write(97); outputStream.write(98); outputStream.write(99); } catch (IOException e) { e.printStackTrace(); } } }法二:public class Demo9_2 { public static void main(String[] args) { //加了 true, 实现了追加写的作业原来的内容不消失 try(OutputStream outputStream new FileOutputStream(./1.txt,true)) { // 97 十进制表示 a outputStream.write(97); outputStream.write(98); outputStream.write(99); } catch (IOException e) { e.printStackTrace(); } } }法三public class Demo9_3 { public static void main(String[] args) { try(OutputStream outputStream new FileOutputStream(./1.txt,true)) { byte[] bytes {97,98,99}; outputStream.write(bytes); }catch (IOException e) { e.printStackTrace(); } } }法四ublic class Demo9_4 { public static void main(String[] args) { try (OutputStream outputStream new FileOutputStream(./1.txt,true)) { byte[] bytes {97,98,99,100,101,102,103,104,105,106}; outputStream.write(bytes,2,3); } catch (IOException e) { e.printStackTrace(); } } }二、字符流读写单位字符 (char)即 16 位 Unicode 字符。读取方式它专门用于读取文本。它在底层其实也是读取字节但它会根据指定的编码规则如 UTF-8、GBK自动将“字节”翻译成“人类可读的字符”。适用纯文本文件.txt, .java, .html 等。使用字符流读取数据public class Demo10 { public static void main(String[] args) { try(Reader reader new FileReader(./1.txt)) { //使用 read 方法读取数据 // while(true) { // int data reader.read(); // if(data -1) { // break; // } // char c (char)data; // System.out.println(c); // } while(true) { char[] chars new char[1024]; int n reader.read(chars); if(n -1) { break; } for (int i 0; i n; i) { System.out.println(chars[i]); } } } catch(IOException e) { e.printStackTrace(); } } }1.int read()这是最基本的方法用于逐个字符读取。2.int read(char[] cbuf)此方法通过字符数组进行批量读取能显著提升读取效率。3.int read(char[] cbuf, int off, int len)这是最灵活的重载方法允许将字符读入数组的指定部分。使用字符流写数据public class Demo11 { public static void main(String[] args) { try(Writer writer new FileWriter(./1.txt,true)) { writer.write(我); writer.write(真); writer.write(美); char[] chars {我,真,美}; writer.write(chars); String s 你也挺美的; writer.write(s); }catch (IOException e) { e.printStackTrace(); } } }1、void write(int c)功能写入单个字符。参数c是一个表示字符的整数0-65535对应Unicode字符。示例writer.write(65); // 写入字符 A writer.write(H); // 直接写入字符 H2、void write(char[] cbuf)功能写入整个字符数组cbuf中的所有字符。示例char[] chars {H, e, l, l, o}; writer.write(chars);3、void write(char[] cbuf, int off, int len)功能写入字符数组cbuf中从索引off开始的len个字符。这是对字符数组进行部分写入的精确控制方法。示例char[] chars {H, e, l, l, o}; writer.write(chars, 0, 3); // 只写入 Hel4、void write(String str)功能写入整个字符串str。示例writer.write(Hello, World!);5、void write(String str, int off, int len)功能写入字符串str中从索引off开始的len个字符。这是对字符串进行部分写入的精确控制方法。参数str要写入的字符串。startingIndex(off)获取字符部分的起始索引。lengthOfstring(len)要写入的字符串长度。示例String str GeeksForGeeks; writer.write(str, 0, 5); // 写入 Geeks[11](ref)三、字节流与字符流的区别假设文件里存的是中文字符“中”在磁盘上UTF-8编码它实际上占用了 3 个字节数据可能是0xE4 0xB8 0xAD。字节流读取它会读出 3 个独立的字节E4、B8、AD。如果你直接把这些字节转成字符串打印可能会显示乱码比如涓因为它不知道这 3 个字节合起来才表示一个“中”字。字符流读取它会根据编码规则UTF-8把这 3 个字节自动拼装、翻译最终给你返回一个字符中。