javaSE————文件IO(2)、

javaSE————文件IO(2)、

文件内容的读写——数据流

我们对于文件操作使用流对象Stream来操作,什么是流对象呢,水流是什么样的,想象一下,水流的流量是多种的,可以流100ml,也可以流1ml,流对象就和水流很像,我们可以一次读取100个字节,或者一次读取1个字节;

1,字节流

1)inputStream

先来使用inputStream,这个是字节流的输入,inputStream是抽象类,和下面的outputStream是一样的,我们需要FileInputStream来实例化对象,FileInputStream的构造方法:

签名说明
FileInputStream(File file1)可以使用file构造文件输入流
FileInputStream(String str)也可以使用文件路径构造输入流

那么inputStream有啥方法呢:

返回类型签名说明
int read()一次就读一个字节,读完了返回-1
intread(byte[] byte)一次读字节数组这么长的数据,返回-1就说明读完了
intread(byte[] byte,int start,int len)一次读取start到len的数据,读完了返回-1
voidclose()关闭输入流

用代码展示输入流:我们这里注意使用这些方法会抛异常,

InputStream inputStream = null; try { inputStream = new FileInputStream("C:/cctalk/java代码容易犯错的知识点/Demo/QQ截图20240915161600.png"); } catch (FileNotFoundException e) { throw new RuntimeException(e); } finally { inputStream.close(); }

这里推荐使用try-with-resources,可以自动去close,为啥我们一定要去close呀,之间学数据结构都不用像c一样嗷嗷释放,因为文件操作不属于内存管理,GC垃圾回收不管他,我们嘚自己去关闭,不关闭他有什么影响呢,还记得进程中PCB中的文件描述符表吗,我们每打开一个程序就会在文件描述符表上自动创建一个固定长度的顺序表,就会申请一个表项,这个不会去扩容的,一直申请,不关闭,表项就没了;

 } try (InputStream inputStream = new FileInputStream("C:/cctalk/java代码容易犯错的知识" + "点/Demo/QQ截图20240915161600.png")){ while (true){ int a = inputStream.read(); if(a==-1){ break; } System.out.println(a); } }

 我们在try中实例对象就相当于打卡了这个文件,如果FileInputStream爆红了,就说明文件不存在了,代码是一次只读取一个字符的情况,读到数据的时候,就会把读到的字符返回给a,因为是字节,所以会返回0-255的数值,在试试一次读取多个字节:

try (InputStream inputStream = new FileInputStream("C:/cctalk/java代码容易犯错的知识" + "点/Demo/QQ截图20240915161600.png")){ while (true){ byte[] bytes = new byte[20]; int a = inputStream.read(bytes); if(a==-1){ break; } for (int i = 0; i < 20; i++) { System.out.print(bytes[i]+" "); } System.out.println(); } }

我们创建一个字节数组,每次读取固定byte.length长度的字符,再输出,看看结果

 此外呢,我们还可以通过Scanner来读取,我们在网络编程TCP协议中常常使用Scanner来代替intputStream,但是这里不太行,因为,Scanner会根据inputStreamReader把字节流转化为字符流,我们传的是一个图片,图片是二进制指令,我们需要遵守他们字节的编码方法,我们现在重新弄一个路径,试试读取字符;

我们在test中写3个哈哈哈;

InputStream inputStream = new FileInputStream("C:/cctalk/java代码容易犯错的知识点/Demo/test.txt"); Scanner scanner = new Scanner(inputStream); while (scanner.hasNext()){ String a = scanner.next(); System.out.print(a+" "); }

 

2)outputStream

outputStream就是字节流的输出了,同样也是一个抽象类,需要FileOutputStream来辅助实例对象,FileOutputStream的构造方法是和FileIntputStream一样的,我们来看看OutputStream的的方法:

返回值签名说明
voidwrite(int b)写入所给的字节数据
voidwrite(byte[] b)写入长度为b.length的字节数据
int write(byte[] b,int set,int len)将字节数组从Set开始,写入len个长度
voidclose()关闭字节流
voidflush()

这里的flush我们拿出来单独说,这个是什么方法呢,我们文件IO操作的数据是很慢的,我们不可能去等这个操作,一个一个的把这些数据写入到设备中,所以我们会先把数据攒到缓冲区中,等到缓冲区满了之后我们再把这些数据一起写入设备,所以我们可以使用这个操作,来冲刷缓冲区,不等他满了,直接把数据写入设备;

还是使用代码来看看:

try (OutputStream outputStream = new FileOutputStream("C:/cctalk/java代码容易犯错的知识点/Demo/test.txt")){ outputStream.write(97); outputStream.write(98); outputStream.write(98); } catch (IOException e) { throw new RuntimeException(e); }

我们写入几个字符,应该是abb;

test文档中出现了abb,哎不对呀,我们之前不是在这写了哈哈哈三个字吗,哪去了,我们的write操作是会覆盖之前的内容的,如果想要接着写我们要使用追加模式

 try (OutputStream outputStream = new FileOutputStream("C:/cctalk/java代码容易犯错的知识点/Demo/test.txt" ,true)){ outputStream.write(76); } catch (IOException e) { throw new RuntimeException(e); }

实例化的构造方法中写true,就可以追加的写了;

这里多了一个l,再试试多行的写入

try (OutputStream outputStream = new FileOutputStream("C:/cctalk/java代码容易犯错的知识点/Demo/test.txt" ,true)){ byte[] bytes = new byte[]{99,98,97,96,95}; outputStream.write(bytes); } catch (IOException e) { throw new RuntimeException(e); }

我们还可以试试,如果我们没有这个test文件会怎么样呢,怎么去写入呢,

 try (OutputStream outputStream = new FileOutputStream("C:/cctalk/java代码容易犯错的知识点/Demo/test4.txt")){ byte[] bytes = new byte[]{99,98,97,96,95}; outputStream.write(bytes); } catch (IOException e) { throw new RuntimeException(e); } 

我们写不存在的test4;

它自己创建了对应的文件并且写入了数据;

读数据有Scanner,那么写有没有对应的呢?有的兄弟有的,像这样的‘’‘’‘’‘’哈哈,不开玩笑了,我们还可以使用PrintWriter,来上代码:

try (OutputStream outputStream = new FileOutputStream("C:/cctalk/java代码容易犯错的知识点/Demo/test4.txt")){ PrintWriter printWriter = new PrintWriter(outputStream); printWriter.print(98); printWriter.println(99); printWriter.flush(); } catch (IOException e) { throw new RuntimeException(e); }

 

也是可以的;


2,字符流

我们使用字节流读取二进制数据,我们为啥还要字符流呢,通过编码方式,直接得到一堆字符不香吗;

1)Reader

我们使用Reader读数据,

public static void main(String[] args) { try(Reader reader = new FileReader("C:/cctalk/java代码容易犯错的知识点/Demo/test4.txt")){ while (true){ char[] chars = new char[1024]; int b = reader.read(chars); if(b==-1){ break; } for (int i = 0; i < b; i++) { System.out.print(chars[i]); } } } catch (IOException e) { throw new RuntimeException(e); } }

这就是我往test中放的,我们要注意java的编码和idea的编码方式,我这里的都是utf-8,如果不同的话是识别不出来的;

2)Writer

我们使用Writer来写入数据:

try(Writer writer = new FileWriter("C:/cctalk/java代码容易犯错的知识点/Demo/test4.txt")){ char[] chars = new char[]{'H','E','l','l','o'}; writer.write(chars); } catch (IOException e) { throw new RuntimeException(e); }

2,练习

我们来几个小练习

1)扫描指定⽬录,并找到名称中包含指定字符的所有普通⽂件(不包含⽬录),并且后续询问⽤⼾是否 要删除该⽂件

 public class Demo2 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.println("请输入要找的目录"); String rootDir = scanner.next(); File file = new File(rootDir); if(!file.isDirectory()){ System.out.println("这不是个目录"); return; } System.out.println("请输入要删除的关键字"); String key = scanner.next(); find(file,key); } public static void find(File rootDir,String key){ File[] files = rootDir.listFiles(); if(files==null){ return; } for (File file:files){ System.out.println("正在遍历"+file.getAbsoluteFile()); if(file.isFile()){ dealFile(file,key); }else { find(file,key); } } } public static void dealFile(File file,String key){ if(file.getName().contains(key)){ System.out.println("发现文件,是否要删除呢,删除输入y"); Scanner scanner = new Scanner(System.in); String s = scanner.next(); if (s.equals("y")){ file.delete(); }else { return; } }else { return; } } } 

代码实现,我们现在藏几个文件:

"C:\cctalk\java代码容易犯错的知识点\Demo\demo2\新建文件夹\test4.txt" 

看看他能不能把5个带关键字的都找到,

成功找到了;

2)进行普通文件的复制

"C:\cctalk\java代码容易犯错的知识点\Demo\test4.txt"

"C:\cctalk\java代码容易犯错的知识点\Demo\test1.txt"

我们把后面的文件复制到这个新建文件夹中;

public class Demo3 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.println("请输入源文件路径"); String src = scanner.next(); File file = new File(src); if (!file.isFile()){ System.out.println("输入的不是源文件路径或者源文件不存咋"); return; } System.out.println("请输入目标文件路径"); String destPath = scanner.next(); File file1 = new File(destPath); if(!file1.getParentFile().isDirectory()){ System.out.println("输入的目标文件路径的父目录不存在"); return; } System.out.println(file.getAbsoluteFile()); System.out.println(file1.getAbsoluteFile()); try (InputStream inputStream = new FileInputStream(file); OutputStream outputStream =new FileOutputStream(file1)){ while (true){ byte[] bytes = new byte[1024]; int a = inputStream.read(bytes); if(a==-1){ break; } outputStream.write(bytes,0,a); } } catch (FileNotFoundException e) { throw new RuntimeException(e); } catch (IOException e) { throw new RuntimeException(e); } } }

我们就能看到

text1的数据复制到test4上了;

3)扫描指定内容并找到名称或者内容包含指定字符的文件;

C:\cctalk\java代码容易犯错的知识点

"C:\cctalk\java代码容易犯错的知识点\Demo\demo2\demo3\java.txt"

"C:\cctalk\java代码容易犯错的知识点\Demo\demo2\demo3\demo4\214.txt"

我们在第一个目录中找后面两个,第三个的内容包含java关键字的:

public class Demo4 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.println("请输入要搜索的内容,输入目录"); String src = scanner.next(); File file = new File(src); if(!file.isDirectory()){ System.out.println("输入的不是目录"); return; } System.out.println("请输入关键字"); String key = scanner.next(); find(file,key); } public static void find(File file,String key){ File[] files = file.listFiles(); if(file==null){ return; } for (File file1:files){ if (file1.isFile()){ dealFile(file1,key); }else { find(file1,key); } } } public static void dealFile(File file,String k){ if (file.getName().contains(k)){ System.out.println("文件名包含" + file.getName()); return; } StringBuffer stringBuffer = new StringBuffer(); try (Reader reader = new FileReader(file)){ while (true){ char[] chars = new char[1024]; int a = reader.read(chars); if (a==-1){ break; } stringBuffer.append(chars,0,a); } } catch (FileNotFoundException e) { throw new RuntimeException(e); } catch (IOException e) { throw new RuntimeException(e); } if(stringBuffer.indexOf(k)>=0){ System.out.println("文件内容包含"+file.getName()); } } } 

OK啦

Read more

深入解析WebView的概念、功能、应用场景以及使用过程中的优势与挑战

深入解析WebView的概念、功能、应用场景以及使用过程中的优势与挑战

🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_ZEEKLOG博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》、《前端求职突破计划》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入门到实战全面掌握 uni-app》 文章目录 * * 一、引言 * 二、WebView概述 * 三、WebView的功能与应用场景 * 四、WebView的优势与挑战 * 五、WebView的使用示例 * 六、总结 摘要: 本文详细介绍了App中WebView的概念、功能、应用场景以及使用过程中的优势与挑战。通过对WebView的深入剖析,帮助开发者更好地理解和运用这一技术,在App开发中实现更丰富的功能和更好的用户体验。 一、引言 在移动应用开发领域,为了在App中展示网页内容、集成Web应用或实现与网页的交互功能,WebView是一种常用的技术手段。它为开发者提供了一种在原生App中嵌入Web内容的

By Ne0inhk

前端转型AI的“第一公里”:如何建立正确的AI心智模型?

前端转型AI的“第一公里”:如何建立正确的AI心智模型? 在过去的一年里,我见证了太多前端同行的焦虑与迷茫。AI浪潮袭来,很多人匆忙上阵,学会了调用OpenAI的API,甚至跑通了LangChain的Demo,但在实际落地时却频频踩坑。 我们习惯了确定性的世界:输入1 + 1,输出必然是2;写了display: flex,布局必然改变。然而,AI开发是一个概率性的世界:同样的Prompt,两次调用可能得到截然不同的结果。这种底层逻辑的冲突,是前端转型AI最大的“拦路虎”。 很多前端工程师把大模型仅仅当成一个“智能API接口”,试图用传统的硬编码逻辑去控制它,结果往往是Prompt越写越长,系统却越来越不稳定。这并非技术能力不足,而是心智模型尚未完成迁移。 从“函数思维”到“上下文思维” 传统前端开发的核心是“函数思维”:我们定义输入、处理逻辑和输出,追求的是精准控制。但在AI应用开发中,这种思维必须升级为“上下文思维”。 大模型本质上是一个“概率预测机”。它不像函数那样执行指令,而是像人一样理解语境。前端开发者转型AI的第一步,不是去学Python深度学习框架,而是学会如

By Ne0inhk

WebPShop插件完整指南:让Photoshop完美支持WebP图像格式

WebPShop插件完整指南:让Photoshop完美支持WebP图像格式 【免费下载链接】WebPShopPhotoshop plug-in for opening and saving WebP images 项目地址: https://gitcode.com/gh_mirrors/we/WebPShop 作为现代图像格式的领军者,WebP以其卓越的压缩效率和动画支持能力,正在逐步改变数字图像的处理方式。然而,专业设计师在使用Photoshop时常常面临一个尴尬的现实:原生不支持WebP格式。WebPShop插件应运而生,为Photoshop用户提供了完整的WebP格式解决方案。 🤔 为什么需要WebPShop插件? 痛点问题分析 * Photoshop原生无法打开.webp文件,导致工作流程中断 * 无法直接保存为WebP格式,必须依赖第三方转换工具 * 缺乏专业的压缩参数控制,无法优化图像质量与文件大小 * 动态WebP动画处理能力缺失,影响创意表达 解决方案概述 WebPShop插件通过开源方式,为Photoshop添加了完整的WebP格式支持。无论是

By Ne0inhk

【GitHub项目推荐--Happy Coder:Claude Code的移动端与Web客户端】⭐⭐⭐

简介 Happy Coder 是一个为Claude Code和Codex设计的移动端和Web客户端,支持实时语音功能、端到端加密,功能齐全。该项目由slopus团队开发,旨在让开发者能够随时随地监控和控制他们的AI编程助手。 🔗 GitHub地址 : https://github.com/slopus/happy 📱 核心价值 : 移动访问 · 实时监控 · 端到端加密 · 多设备切换 · 开源透明 项目背景 : * 移动办公 :远程工作需求增长 * AI编程 :AI编程助手普及 * 设备切换 :多设备协同需求 * 隐私安全 :代码安全需求 * 开发者工具 :开发者工具创新 项目特色 : * 📱 移动访问 :手机访问Claude Code * ⚡ 实时同步 :实时状态同步 * 🔐 端到端加密 :完全加密保护 * 🔔 推送通知 :智能推送提醒 * 🔄 设备切换 :无缝设备切换 技术亮点 : * 加密技术 :端到端加密 * 实时通信 :实时数据同步

By Ne0inhk