java针对文件的操作有两种1.文件系统操作 File类指定的路径可以使一个不存在的路径。2,文件内容操作,流对象。
流也分为两种1)字节流(二进制文件):以字节为基本单位读写的使用InputStream()和OutputStream进行读写。
2) 字符流(文本文件):以字符为基本读写单位使用Reader() 和 Writer()进行读写。
文件操作内容有很多,比如打开文件,关闭文件在java中允许一种方法是为了防止我们打开过多的文件导致指定进程描述符表长度不够实用导致程序出现问题,因为每打开一个文件,都需要消耗制定进程描述符表上的一个项文件描述符表的长度是有限的(不同的系统不一样,也是可以配置的)。
try(InputStream inputStream = new FileInputStream("./test.txt")){ }catch(IOException e){ e.printStackTrace(); }
通过这种方法我们在try{}内部就可以使用我们所打开的文件除了try的{}那么这个文件将会自动关闭,避免因为开启的文件过多导致文件描述符表不共用,当然我们也可以通过close()方法直接关闭,但是当使用这种方法的时候要注意当代码比较多的时候,不要忘记关闭文件。
在文件中我们可以使用read()方法进行读操作,这种方法有三种形式:
接下来我们逐个介绍,没有参数的read()方法 :
这个方法有一个int类型的返回值,表示的是读取的字节个数,如果个数在0到255之间,表示读取的字节的ASCll值,如果达到流的末尾,则返回-1,表示没更多的数据可供读取,它的用法也十分简单:
public static void main(String[] args) throws IOException { File file = new File("./test.txt"); file.createNewFile(); try(InputStream inputStream = new FileInputStream("./test.txt")){ int n = inputStream.read(); while(n!=-1){ System.out.println((char)n); n = inputStream.read(); } }catch(IOException e){ e.printStackTrace(); } }
通过这种方式我们就可以访问test.txt中的内容了,如果文件中是 此类数据:
那么返回的是各个字符的ASCll值,强转为char类型后自然就是一个字节,但是如果文本文件里是字符那么就无法通过这种方式进行输出了,因为在java中字符所占字节是有所不同的,比如汉字等字符。
如果是汉字
需要通过另一方式更好描述:
public static void main(String[] args) throws IOException { File file = new File("./test.txt"); file.createNewFile(); try(InputStream inputStream = new FileInputStream("./test.txt")){ int n = inputStream.read(); while(n!=-1){ System.out.println(Integer.toHexString(n)); n = inputStream.read(); } }catch(IOException e){ e.printStackTrace(); } }
通过这种方式运行结果为:
由此可知一个汉字占据三个字节,接下来的方法我们使用字母来表示更加简单一些,至于汉字的读写我们有其他的方法进行表述之后我们会逐一进行介绍。
read(byte[] b) 这个版本可以理解为工厂不仅有输出还有输入,将所读的内容输入到 b 数组中,我们可以同过访问b数组中的内容即可知到文件中的内容,需要贴别注意的是这里的数组不一定会用完也可能会有剩余,:
public static void main(String[] args) { try(InputStream inputStream = new FileInputStream("./test.txt")){ byte[] buf = new byte[1024]; while(true){ int n = inputStream.read(buf); if(n==-1) break;; } System.out.println(Arrays.toString(buf)); }catch(IOException e){ e.printStackTrace(); } }
通过这种方式就把test.txt文件中的内容以ASCll值形式存储到buf数组当中了,输出的结果为:
文件里放的为:aaabbbccddd所以他们的ASCll值预支对应,我们可以看到buf数组显然没有用完仍有很大一本分没有使用。
read(byte[] b,int off,int len)在这里off :从数组的哪个偏移量开始存储数据,len:要读取道德最大字节数注意这里的len包含off,假设len原本位置为a也就意味这len = off+a也就意味这len不能草果数组的长度;
public static void main(String[] args) { try(InputStream inputStream = new FileInputStream("./test.txt")){ byte[] buf = new byte[1024]; while(true){ int n = inputStream.read(buf,0,buf.length); if(n==-1) break;; for (int i=0;i<n;i++){ System.out.println(buf[i]); } } }catch(IOException e){ e.printStackTrace(); } }
这种方法的结果同只有一个参数的方法作用效果除了变异量的差别其他的并无二异,方法是从0偏移量为0开始存储的所以,这里第一次直接将文本中的内容放到buf数组当中,第二次n等于-1循环停止,过程结束;
OutputStream 写文件
写文件同样也有许多方法:
写文件有这三个冲在版本使用同输出相比是大同小异;
write(int b)
: 写入一个字节(范围从 0 到 255)。write(byte[] b)
: 将字节数组写入输出流。write(byte[] b, int off, int len)
: 从字节数组的指定偏移量 (off) 开始写入指定长度 (len) 的字节。
相对应的是
write(byte[] b)是只输入不输出,数组b中的内容放到文本文件中后就结束了。
需要特别注意的是这里每输入一次文本中的内容就重置一次,如果我们想要保存我们之前输入的内容,那么我们需要加入一个参数true:
public static void main(String[] args) { try(OutputStream outputStream = new FileOutputStream("./test.txt",true)){ }catch(IOException e){ e.printStackTrace(); } }
通过这种方式我们就可以不断地进行输入并保存我们之前输入过的内容。
另外读取文件是还有一个十分有用的工具类Scanner:
public static void main(String[] args) { File file = new File("./test.txt"); try(OutputStream outputStream = new FileOutputStream("./test.txt",true)){ Scanner scanner = new Scanner(file); String str = scanner.next(); System.out.println(str); }catch(IOException e){ e.printStackTrace(); } }
通过这种方式就更好的读取文本,并可以方便地进行分隔和格式化。