大家好,又见面了,我是你们的朋友全栈君。
java.io.File类——对计算机操作系统中的文件和文件夹
一、绝对路径和相对路径异同点:
两者的相同之处,在于两者都是对图像,音乐,网址,视频等文件资源的引用方法。
两者的不同之处,在于描述目录路径时,所采用的参考基准点不同。
**绝对路径:**直接指明文件在硬盘上真正存在具体位置或者是以Web站点根目录为参考的完整路径。绝对路径是规定死的目录,直观清晰,但被网页引用的文件不能随意挪动。当多个网页引用同一个文件时,所使用的路径都是相同的。
**相对路径:**舍去磁盘盘符、计算机名等信息,以引用文件的网页所在文件夹位置为参考,建立出的基准根目录。当保存于不同目录的网页引用同一个文件时,所使用的相对路径不同。
二、在什么情况下使用绝对路径?
通常情况下,只在自己的计算机上对网页进行编辑操作,不拷贝到别的电脑或者服务器,这时可以使用绝对路径。
三、在什么情况下使用相对路径?
在大多情况下,进行网页编程时,强烈推荐使用相对路径。如果使用绝对路径来指定文件的位置,在自己的计算机上,浏览可能是正常显示,但如果上传到Web服务器上浏览,很有可能因为路径不对,导致图片等文件不能正常显示。而使用相对路径,可以减少因网页和程序文件存储路径变化,造成的网页不正常显示、程序不正常运行现象。使用某些网页设计软件引用文件时,会自动使用相对路径,极大的便利了网站管理。 ———————————————— 版权声明:本文为CSDN博主「你们这样一点都不可耐」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/vanarrow/article/details/105459387
package study1118;
import java.io.File;
public class Test04 {
public static void main(String[] args) {
//以绝对路径新建文件对象,注意参数是文件路径为字符串格式,注意一个\表示转义,所以这里要写两个\
File f = new File("F:\\重新认识计算机\\JavaSe\\基础语法\\src\\study1118\\新建文件夹\\ceshi.txt");
//获取文件名或当前文件夹的名字——getName()
File f1= new File("F:\\重新认识计算机\\JavaSe\\基础语法\\src\\study1118");
System.out.println(f.getName()); //ceshi.txt
System.out.println(f1.getName()); //study1118
//以相对路径新建文件对象
File f2 = new File("src\\study1118\\新建文件夹\\ceshi.txt");
//获取当前文件或文件夹的路径——getPath()
// (获取的是你创建文件对象时我们在程序中写入的路径,可能是绝对,可能是相对)
System.out.println(f.getPath()); // F:\重新认识计算机\JavaSe\基础语法\src\study1118\新建文件夹\ceshi.txt
System.out.println(f1.getPath());// F:\重新认识计算机\JavaSe\基础语法\src\study1118
System.out.println(f2.getPath());// src\study1118\新建文件夹\ceshi.txt
//获取绝对路径————getAbsoluteFile
System.out.println(f2.getAbsoluteFile());
//返回父级目录
System.out.println(f2.getParent());
//重命名
f.renameTo(new File("F:\\重新认识计算机\\JavaSe\\基础语法\\src\\study1118\\新建文件夹\\nop.txt"));
//判断文件是否存在,是否可读,可写(如果文件不存在均返回false)
//文件属性可以设置只读
File f01 = new File("C:\\Users\\12958\\Desktop\\abc");
System.out.println(f01.exists());
System.out.println(f01.canRead());
System.out.println(f01.canWrite());
//判断当前文件对象是否为文件
System.out.println(f01.isFile()); //false 此处abc是文件夹
//判断当前文件对象是否为文件夹
System.out.println(f01.isDirectory());
File f02 = new File("C:\\Users\\12958\\Desktop\\abc\\test.txt");
//获取文件最后修改时间
System.out.println(f02.lastModified());//返回毫秒数
//返回文件长度——单位:字节数
System.out.println(f02.length());
}
}
小练习: 判断文件是否存在(exist),不存在就生成(creatNewFile)新的文件,注意异常处理。
public class Test05 {
public static void main(String[] args) {
File f1 = new File("C:\\Users\\12958\\Desktop\\abc\\test.txt");
File f2 = new File("C:\\Users\\12958\\Desktop\\abc\\test01.txt");
System.out.println(f1.exists());//true
System.out.println(f2.exists());//false
if(!f2.exists()){
try {
f2.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
//删除文件
f2.delete();
}
}
目录相关的操作
public class Test05 {
public static void main(String[] args) {
//(此时并不存在efg目录)
File f1 = new File("C:\\Users\\12958\\Desktop\\abc\\efg");
//创建单层目录
f1.mkdir();
//(此时并不存在 hello\world\小红)
File f2 = new File("C:\\Users\\12958\\Desktop\\abc\\hello\\world\\小红");
//创建多层目录
f2.mkdirs();
//输出当前路径下一级的所有文件和文件夹 的 名称
// f.list()返回的是字符串数组
File f3 = new File("C:\\Users\\12958\\Desktop\\abc");
for (String s : f3.list()) {
System.out.println(s);
}
//输出当前路径下一级的所有文件和文件夹 的 绝对路径
// 返回的是File型的数组
File f4 = new File("C:\\Users\\12958\\Desktop\\abc");
for (File fil : f4.listFiles()) {
System.out.println(file);
}
}
}
小练习: 完全遍历一个文件夹(要访问到其最深层的文件夹下)——递归方法 traversal ——n.遍历,穿越
package study1118;
import java.io.File;
public class Test06 {
public static void main(String[] args) {
File file = new File("C:\\Users\\12958\\Desktop\\abc\\hello");
new Test06().traversal(file);
}
//递归遍历文件
public void traversal(File file){
if(file.isFile()){
System.out.println(file.getAbsolutePath()+"是文件");
}else {
System.out.println(file.getAbsolutePath() + "是文件夹");
//并进入子文件,获取当前文件下的子文件夹或者文件的File对象
File[] fs = file.listFiles();
if (fs != null && fs.length > 0) {
for (File f : fs) {
traversal(f);
}
}
}
}
}
输出:
C:\Users\12958\Desktop\abc\hello是文件夹 C:\Users\12958\Desktop\abc\hello\world是文件夹 C:\Users\12958\Desktop\abc\hello\world\小红是文件夹 C:\Users\12958\Desktop\abc\hello\world\小红\萨达是文件夹 C:\Users\12958\Desktop\abc\hello\world\小红\萨达\撒打是文件夹 C:\Users\12958\Desktop\abc\hello\world\小红\萨达\撒打\打滴滴是文件夹
notes: 1. Java中IO流涉及很多类,均是由以上四个抽象基类派生出来的,且这些子类的命名规则都是由其父类名为后缀。 2. 这些IO流,都是计算机与硬盘之间发生的IO操作(即CPU与IO设备),速度相对较慢,这个速度受到硬盘读写速度的制约。 3. 为了能够提高读写速度,计算机设置了介于CPU与IO设备之间的缓冲区,从而引出缓冲流的概念(后面详细说)
IO操作都有异常,需要异常捕获
将文件中的内容以字节形式读入字节数组,然后以字符串形式输出
import java.io.FileInputStream;
public class Test07 {
public static void main(String[] args) {
try {
// 新建 文件的字节输入流对象
FileInputStream in = new FileInputStream("C:\\Users\\12958\\Desktop\\abc\\test.txt");
//设置一个byte型字节数组,接收读取文件内容
byte[] b = new byte[100];
//把输入流对象中的字节读到字节数组b中
in.read(b);
//将字节数组转换为字符串
String s = new String(b);
System.out.println(s); //这两句也可以写成一句System.out.println(new String(b));
//notes:流在使用完毕之后一定要关闭
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
上述程序可能会涉及到一个问题——读多了,也就是数组长度比文件内字节数更大,这样输出的字符串末尾可能会有其他不相关信息。
所以需要01限制从文件中读到字节数组中的长度,或者02限制后面把字节数组转换为字符串的长度,可以用read方法获取到读的长度,以这个长度来做限制。
改进如下:
package study1120;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class Test01 {
public static void main(String[] args) {
try {
FileInputStream in = new FileInputStream("C:\\Users\\12958\\Desktop\\abc\\test.txt");
byte[] b = new byte[100];
int len=0 ;
while((len= in.read(b))!=-1){
System.out.println(new String(b,0,len));
// String的三个参数(需要转换成字符串的数组,起始位置,终点位置)
}
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
常用操作
写一个静态文件节流输出方法,把一个字符串写到指定文件,若文件不存在要自动新建
import java.io.FileOutputStream;
public class Test02 {
/** * 文件字节流输出方法 */
public static void egFileOutputStream(){
try {
//此处没有文件test01,会自行新建
FileOutputStream out = new FileOutputStream("C:\\Users\\12958\\Desktop\\abc\\test01.txt");
String str="yesterday, I'm sorrow";
out.write(str.getBytes());
//out.write()把数据写到内存中
//str.getBytes()把字符串转化为字节数组
out.flush();//把内存中的东西冲入硬盘
System.out.println("完成");
out.close();//关闭输出流
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Test02.egFileOutputStream();
}
}
常用操作
小练习:
编写一个程序,把一个文件复制到指定文件夹下
思路:写一个静态文件节流拷贝方法,有两个参数,输入路径和输出路径,然后源文件读书,写入到目标文件。
package study1120;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class Test03 {
/** * 复制文件到指定位置 * @param inPath 源文件路径 * @param outPath 目标路径 */
public static void copyFile(String inPath,String outPath){
try {
FileInputStream in = new FileInputStream(inPath);
FileOutputStream out = new FileOutputStream(outPath);
byte[] b = new byte[1024];//缓冲数组
int len=0;
while((len=in.read(b))!=-1){
out.write(b,0,len);//从缓冲数组b的0号位置开始写到len
}
out.flush();//写到内存的数据冲到硬盘
//关闭流,后开的先关
out.close();
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Test03.copyFile("C:\\Users\\12958\\Desktop\\abc\\test.txt","C:\\Users\\12958\\Desktop\\abc\\hello\\test.txt");
}
}
notes:
文件字节流是通用的,不仅可以操作txt文档,也可操作其他任何类型的文件,比如图片,视频,音频。因为字节流底层直接使用的是二进制。
关于int len()方法
import java.io.FileInputStream;
import java.io.IOException;
public class Test07 {
public static void main(String[] args) {
System.out.println("hello world");
//新建一个字节数组作为缓冲区
byte[] buffer = new byte[1024];
try {
//获取在buffer中读取了多少字节数
int len =System.in.read(buffer);//出现Unhandled Exception,需要捕获异常
String s = new String(buffer, 0, len);//将字节数组buffer中从0开始到第len个字节元素转换为字符串
System.out.println("读到了"+len+"个字节");
System.out.println("内容为:"+s);
System.out.println("字符串长度为:"+s.length());
} catch (IOException e) {
e.printStackTrace();
}
}
}
输出结果:
hello world **键盘输入:**1231456 读到了8个字节 内容为:1231456
字符串长度为:8
解释: 读到八个字节是因为后面还有一个回车,内容和长度中间空了一行是因为s中本来最后一个输入的就是回车,而s又是通过println输出的,所以多一行空格,字符串长度为8也是因为包含了一个换行符(单位是字符)
更改上面程序的键盘输入,加入一些中文文字会得到以下输出结果:
输出结果:
hello world **键盘输入:**123中国1456 读到了12个字节(java中一个汉字占两个字节) 内容为:1231456
字符串长度为:9(此处是字符串长度,汉字在字符串中占一个字符)
FileReader类——文件字符输入流
FileWriter类——文件字符输出流
这两个字符类与上面两个字节类的区别在于,读出来的东西放到什么数组中去
notes:
缓冲字节输入流,输出流的应用
package study1120;
import java.io.*;
public class Test04 {
/** * 缓冲字节输入流方法 * BufferedInputStream */
public static void testBufferedInputStream() throws Exception {
//新建文件字节输入流对象
FileInputStream in = new FileInputStream("C:\\Users\\12958\\Desktop\\abc\\test.txt");
//新建缓冲字节输入流对象
BufferedInputStream bi = new BufferedInputStream(in);//这里参数是需要一个文件字节输入流对象
//接下来操作输入输出就用这个缓冲对象br了
byte[] b = new byte[1024];
int len=0;
while((len=bi.read(b))!=-1){
System.out.println(new String(b,0,len));
}
//关闭流,后开先关
bi.close();
in.close();
}
/** * 缓冲字节输出流 * BufferedOutputStream */
public static void testBufferedOutputStream() throws Exception{
FileOutputStream out = new FileOutputStream("C:\\Users\\12958\\Desktop\\abc\\tt.txt");
BufferedOutputStream bo = new BufferedOutputStream(out);
String s="hello,baby.";
//将字符串s转换为byte数组写入内存中
bo.write(s.getBytes());
//将内存文件冲入硬盘
bo.flush();
bo.close();
out.close();
}
/** * 缓冲流实现文件的复制 */
public static void copyFile() throws Exception{
//新建缓冲输入流对象
BufferedInputStream br = new BufferedInputStream(new FileInputStream("C:\\Users\\12958\\Desktop\\abc\\tt.txt"));
//新建缓冲输出流对象
BufferedOutputStream bo = new BufferedOutputStream(new FileOutputStream("C:\\Users\\12958\\Desktop\\abc\\hello\\tt.txt"));
byte[] b = new byte[1024];
int len=0;
while((len= br.read(b))!=-1){
bo.write(b,0,len);
}
bo.flush();
bo.close();
br.close();
}
public static void main(String[] args) {
try {
Test04.testBufferedInputStream();
Test04.testBufferedOutputStream();
Test04.copyFile();
} catch (Exception e) {
e.printStackTrace();
}
}
}
缓冲字符输入流,输出流的应用
(与字节的类似,此处不再赘述)
notes:
缓冲是把数据缓冲到内存中
所有的文件都是有编码格式的,对于txt和java文件一般来讲有三种字符编码方式
**转换流的功能:**使文件从字节流转换为字符流。当字节流中的数据都是字符时,转换成字符流操作将会更高效。
(在转换过程中,就需要指定字符编码方式来进行解码编码)
Java中提供了两个转换流:InputStreamReader和OutputStreamWriter
package study1120;
import java.io.*;
public class Test05 {
public static void main(String[] args) {
try {
Test05.testInputStreamReader();
Test05.testOutputStreamWriter();
} catch (Exception e) {
e.printStackTrace();
}
}
/** * 转换输入流 * InputStreamReader */
public static void testInputStreamReader() throws Exception{
//新建字节输入流对象
FileInputStream fs = new FileInputStream("F:\\重新认识计算机\\JavaSe\\基础语法\\src\\study1120\\today.txt");
//将字节输入流对象转换为字符输入流对象
InputStreamReader in = new InputStreamReader(fs, "utf-8");//参数1是字节流对象,参数2是编码方式
// InputStreamReader in = new InputStreamReader(fs, "gbk");// 输出乱码
// notes:在转换字符流的时候,设置的字符及编码要与读取的文件的数据的编码一致
char[] c = new char[100];
int len =0;
while((len=in.read(c))!=-1){
System.out.println(new String(c,0,len));
}
in.close();
fs.close();
}
/** * 转换输出流 * OutputStreamWriter */
public static void testOutputStreamWriter() throws Exception{
FileOutputStream out = new FileOutputStream("C:\\Users\\12958\\Desktop\\abc\\tt.txt");
OutputStreamWriter os = new OutputStreamWriter(out, "utf-8");
os.write("什么是快乐星球");
os.flush();
os.close();
out.close();
}
}
package study1120;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
/** * 标准输入流 */
public class Test06 {
public static void main(String[] args) {
try {
Test06.testSystemin();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void testSystemin() throws Exception {
//创建一个接受键盘输入的输入流对象
InputStreamReader in = new InputStreamReader(System.in);
//把输入流放入缓冲流
BufferedReader bf = new BufferedReader(in);
//一行一行的读入
String s="";
while((s=bf.readLine())!=null){
System.out.println(s);
}
bf.close();
in.close();
}
}
小练习:
把控制台输入的内容写到指定的txt文件中,当接受到字符串over时,结束程序运行
package study1120;
import java.io.*;
public class Test06 {
public static void main(String[] args) {
try {
Test06.writeTotxt();
} catch (Exception e) {
e.printStackTrace();
}
}
//为什么这里写方法都写成静态方法,因为静态方法可以直接通过类名访问,方便测试
//如果是非静态方法,需要new对象后通过对象访问
public static void writeTotxt() throws Exception{
System.out.println("开始输入吧");
InputStreamReader is = new InputStreamReader(System.in);
//输入缓冲流对象
BufferedReader bf = new BufferedReader(is);
//输出缓冲流对象
BufferedWriter out = new BufferedWriter(new FileWriter("C:\\Users\\12958\\Desktop\\abc\\控制台测试文字.txt"));
String s="";
while((s=bf.readLine())!=null){
//从缓冲流对象读到字符串
if(s.equals("over"))break;
out.write(s); //将字符串内容写入内存
}
out.flush();
out.close();
bf.close();
is.close();
System.out.println("输入完毕");
}
}
public static void main(String[] args) {
PrintStream out = System.out;
out.println("hello");
}
import java.io.*;
public class Test07 {
public static void main(String[] args) {
try {
Test07.testDataOutputStream();
Test07.testDataInputStream();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void testDataOutputStream() throws Exception{
//新建一个数据输出流对象(参数:是一个输出流的实例,此处用的是文件输出流实例)
DataOutputStream out = new DataOutputStream(new FileOutputStream("C:\\Users\\12958\\Desktop\\abc\\tt.txt"));
//out.writeBoolean(true);
out.writeDouble(1.35D);
//发现两次写入的东西都是乱码
//所以可知数据输出流写到文件中的基本数据类型的数据是不能直接辨认的,而应该用数据输入流来读取
out.flush();
out.close();
}
public static void testDataInputStream() throws Exception{
DataInputStream in = new DataInputStream(new FileInputStream("C:\\Users\\12958\\Desktop\\abc\\tt.txt"));
//System.out.println(in.readBoolean());
System.out.println(in.readDouble());
//发现只有当读方法和当时写方法匹配时,才能读出正确数据
//上面写的Double,读也就只能读Double
in.close();
}
}
把对象保存到硬盘上(对象的持久化)和对象的网络传输,这两件事引出了对象的输入输出流。
新建一个可序列化的类
package study1120;
import java.io.Serializable;
/** * 支持可序列化与反序列化的类 */
public class Person implements Serializable {
//凡是实现Serializable的接口都有一个表示序列化版本标识符的静态变量
private static final long serialVersionUID=1L;
//用来表明类的不同版本间的兼容性
String name;
int age;
}
实例化一个Person类对象,进行序列化(封装成方法)后存入指定txt文件
package study1120;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
/** * 序列化与反序列化的测试类 */
public class Test08 {
/** * 对象的序列化 */
public static void testSerialize() throws Exception{
//新建对象输出流对象,传入参数是输出流对象(此处是文件输出流对象)
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("C:\\Users\\12958\\Desktop\\abc\\tt01.txt"));
Person p = new Person();
p.name="xiaomi";
p.age=13;
out.writeObject(p);
out.flush();
out.close();
}
public static void main(String[] args) {
try {
Test08.testSerialize();
} catch (Exception e) {
e.printStackTrace();
}
}
}
将txt文件反序列化后读出
public class Test08 {
/** * 对象的反序列化 */
public static void testDererialize() throws Exception{
//新建对象输入流对象,传入参数是输入流对象(此处是文件输入流对象)
ObjectInputStream in = new ObjectInputStream(new FileInputStream("C:\\Users\\12958\\Desktop\\abc\\tt01.txt"));
Object o = in.readObject();//从输入对象流对象中读取对象
Person p = (Person)o;//强转
System.out.println(p.age);
System.out.println(p.name);
in.close();
}
public static void main(String[] args) {
try {
Test08.testSerialize();
Test08.testDererialize();
} catch (Exception e) {
e.printStackTrace();
}
}
}
notes:
对象的序列化与反序列化使用的类要严格一致,包名,类名,类结构等等所有都要一致
package study1121;
import java.io.RandomAccessFile;
/** * 文件的随机读取 */
public class Test01 {
public static void main(String[] args) {
try {
//随机读
Test01.testRandomAccessFileRead();
//随机写
Test01.testRandomAccessFileWrite();
} catch (Exception e) {
e.printStackTrace();
}
}
/** * 方法——随机读 */
public static void testRandomAccessFileRead() throws Exception{
//RandomAccessFile的构造方法有两个参数,文件路径和读写方式
//读写方式有 r,rw,rwd(同步文件内容的更新),rws(同步文件内容和元数据的更新)
RandomAccessFile ra = new RandomAccessFile("C:\\Users\\12958\\Desktop\\abc\\hello\\tt.txt","r");
//设置读取位置的起始点(字符)
ra.seek(5);//这就是随机存储的关键,注意:如果有换行,那换行符也算一个字符
byte[] b = new byte[1024];
int len=0;
while((len=ra.read(b))!=-1){
System.out.println(new String(b,0,len));
}
ra.close();
}
public static void testRandomAccessFileWrite() throws Exception{
RandomAccessFile rw = new RandomAccessFile("C:\\Users\\12958\\Desktop\\abc\\hello\\ttnew.txt", "rw");
//设置写的起始点
rw.seek(0);//0代表从开头写
// rw.seek(rw.length());//rw.length()代表从文件末尾开始写,也就是追加
rw.write("你好".getBytes());
//随机存储不用flush,可直接关闭
rw.close();
}
}
notes:
小结:
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/168483.html原文链接:https://javaforall.cn