产生文件

        File file = new File("abc.txt");
if(!file.exists()){
System.out.println(file.exists());
file.createNewFile();
}
System.out.println(file.getAbsolutePath());

关于临时文件

1).放在指定目录,此时已项目为默认目录

    File file = File.createTempFile("defaultTmp","tmpp",new File("./"));
System.out.println(file.getAbsolutePath());
--------------------------------------------------

/Users/liuxin/work/workspace2/learnJava/./defaultTmp5487876755372558069tmpp

2).放在默认目录

File file = File.createTempFile("defaultTmp",".tmpp");
System.out.println(file.getAbsolutePath()); ------------------------------------------------------------------------
/var/folders/f9/x95426d95ng7wgy7f7yccj3w0000gn/T/defaultTmp1175907986750188229tmpp

3).虚拟机退出时删除临时文件

File file = File.createTempFile("defaultTmp",".tmpp");
file.deleteOnExit();
System.out.println(file.getAbsolutePath());

4).关于后缀

File testFile = new File("testFile");
if(!testFile.exists()){
testFile.mkdirs();
}
testFile.deleteOnExit();
File file = File.createTempFile("defaultTmp","tmpp");
System.out.println(file.getAbsolutePath());
File file2 = File.createTempFile("defaultTmp2",".tmpp",testFile);
System.out.println(file2.getAbsolutePath());
File file3 = File.createTempFile("defaultTmp3",null,testFile);
System.out.println(file3.getAbsolutePath()); =======================================
/var/folders/f9/x95426d95ng7wgy7f7yccj3w0000gn/T/defaultTmp5296324826431648502tmpp
/Users/liuxin/work/workspace2/learnJava/testFile/defaultTmp21551336802243345058.tmpp
/Users/liuxin/work/workspace2/learnJava/testFile/defaultTmp33930717872920538957.tmp

操作目录

1.查看目录下的所有文件

File currentFile = new File(".");
System.out.println(currentFile.getAbsolutePath());
for(File file : currentFile.listFiles()){
System.out.println(file.getName());
}

getParent()的使用方法

File file = new File(".");
System.out.println(file.getAbsolutePath());
System.out.println(new File(file.getAbsolutePath()).getParent()); -----------------------
/Users/liuxin/work/workspace2/learnJava/.
/Users/liuxin/work/workspace2/learnJava getParent()只有在定义文件时有路径时才起作用.

15.2 流

字节流主要由InputStream和OutputStream作为基类,而字符流则主要由Reader和Writer作为基类.

字节流操作的数据单元是8位的字节,而字符流操作的数据单元是16位的字符

节点流和处理流,节点流是低级流,直接跟数据源相接.处理流(也叫包装流)把节点流包装了一层,属于修饰器设计模式.

处理流的功能主要体现在以下两个方面:

1.性能的提高:主要以增加缓冲的方式来提高输入输出的效率

2.操作的便捷:处理流可能提供了一系列便捷的方法来一次输入输出大批量的内容,而不是输入/输出一个或多个水滴

处理流可以嫁接在任何已存在的流的基础上.

15.3.1 InputStream和Reader

InputStream和Reader是所有输入流的抽象基类,本身并不能创建实例来执行.

读取文件的demo

public static void testFile() throws IOException{
// 创建字节输入流
FileInputStream fis = new FileInputStream("a.txt");
// 创建一个长度为1024的“竹筒”
byte[] bbuf = new byte[];
// 用于保存实际读取的字节数
int hasRead = ;
// 使用循环来重复“取水”过程
while ((hasRead = fis.read(bbuf)) > )
{
// 取出“竹筒”中水滴(字节),将字节数组转换成字符串输入!
System.out.print(new String(bbuf , , hasRead ));
}
// 关闭文件输入流,放在finally块里更安全
fis.close();
}

关于fileFilter

File file = new File(".");
String[] nameList = file.list((dir, name) -> name.endsWith(".java")
|| new File(name).isDirectory());
for(String name : nameList)
{
System.out.println(name);
} ================================
.settings
a
bin
lib
result
sqlModify
src
testFile

15.2 理解java的IO流

用字节流读取文件并打印

public static void testFile2() throws IOException{
// 创建字节输入流
FileInputStream fis = new FileInputStream("a.txt");
//读取一个字节,返回的是int,所以要用char强转
System.out.println((char)fis.read());
// 创建一个长度为1024的“竹筒”
byte[] bbuf = new byte[];
//读取5个字节,放在bbuf的index为10的位置
fis.read(bbuf,,);
// 从bbuf中index为10的位置读取5个字节构成字符串
System.out.println(new String(bbuf , , ));
//转换成String后,byte[]不变
System.out.println(new String(bbuf , , ));
// 用于保存实际读取的字节数
int hasRead = ;
// 使用循环来重复“取水”过程
while ((hasRead = fis.read(bbuf)) > )
{
//重新赋值后,byte[]会改变
System.out.println(new String(bbuf , , ));
// 取出“竹筒”中水滴(字节),将字节数组转换成字符串输入!
System.out.println("==============================================");
String test = new String(bbuf , , hasRead );
System.out.println(test);
System.out.println("=================="+new String(bbuf , , hasRead ).length()+"============================");
}
// 关闭文件输入流,放在finally块里更安全
fis.close();
}
打印结果如下
<
?xml
?xml
ncodi
==============================================
on="1.0" encoding="UTF-8"?>
<projectDescription>
<name>learnJava</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription> 我很好啊,看看需不要utf-
==============================================
public static void testFile3() {
try(
// 创建字符输入流
FileReader fr = new FileReader("a.txt")
){
// 创建一个长度为32的“竹筒”
char[] cbuf = new char[];
System.out.println(fr.read(cbuf,,));
System.out.println(new String(cbuf));
// 用于保存实际读取的字符数
int hasRead = ;
// 使用循环来重复“取水”过程
while ((hasRead = fr.read(cbuf)) > )
{
// 取出“竹筒”中水滴(字符),将字符数组转换成字符串输入!
// System.out.print(new String(cbuf , 0 , hasRead));
System.out.print(new String(cbuf));
}
}
catch (IOException ex)
{
ex.printStackTrace();
} }

outPutStream 和 Writer

public static void testFileWriter() {
    //这里a.txt可以不存在,如果不存在回自动生成,但是没搞明白怎么设置编码格式
try(FileWriter fw = new FileWriter("a.txt")) {
fw.write("锦瑟 - 李商隐\r\n");
fw.write("锦瑟无端五十弦,一弦一柱思华年。\r\n");
fw.write("庄生晓梦迷蝴蝶,望帝春心托杜鹃。\r\n");
fw.write("沧海月明珠有泪,蓝田日暖玉生烟。\r\n");
fw.write("此情可待成追忆,只是当时已惘然。\r\n");
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
}

15.4 输入输出流体系

处理流:构造参数是已经存在的流.

节点流:构造参数是物理IO节点

处理流的用法

public static void PrintStream() {
try(
FileOutputStream fos = new FileOutputStream("a.txt");
PrintStream ps = new PrintStream(fos))
{
// 使用PrintStream执行输出
ps.println("普通字符串");
// 直接使用PrintStream输出对象
ps.println(new LearnIO());
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
}

输出结果

普通字符串
learnIO.LearnIO@677327b6

在使用了处理流包装了底层节点之后,关闭输入/输出流资源时,只要关闭最上层的处理流即可。关闭最上层的处理流时,系统会自动关闭被该处理流包装的节点流。

字符串流的用法,似乎没什么用,等发现用处再补充

public static void stringNodeTest() {
String src = "从明天起,做一个幸福的人\n"
+ "喂马,劈柴,周游世界\n"
+ "从明天起,关心粮食和蔬菜\n"
+ "我有一所房子,面朝大海,春暖花开\n"
+ "从明天起,和每一个亲人通信\n"
+ "告诉他们我的幸福\n";
char[] buffer = new char[];
int hasRead = ;
try(
StringReader sr = new StringReader(src))
{
// 采用循环读取的访问读取字符串
while((hasRead = sr.read(buffer)) > )
{
System.out.print(new String(buffer , , hasRead));
}
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
try(
// 创建StringWriter时,实际上以一个StringBuffer作为输出节点
// 下面指定的20就是StringBuffer的初始长度
StringWriter sw = new StringWriter())
{
// 调用StringWriter的方法执行输出
sw.write("有一个美丽的新世界,\n");
sw.write("她在远方等我,\n");
sw.write("哪里有天真的孩子,\n");
sw.write("还有姑娘的酒窝\n");
System.out.println("----下面是sw的字符串节点里的内容----");
// 使用toString()方法返回StringWriter的字符串节点的内容
System.out.println(sw.toString());
}
catch (IOException ex)
{
ex.printStackTrace();
}
}

15.4.3 转换流

InputStreamReader :将字节输入流转换成字符输入流

OutputStreamWriter:将字节输出流转换成字符输出流

经过测试,下面这个程序是有一定问题的,用输入法的时候,会重复输出好多遍

public static void KeyinTest() {
try(
// 将Sytem.in对象转换成Reader对象
InputStreamReader reader = new InputStreamReader(System.in);
// 将普通Reader包装成BufferedReader
BufferedReader br = new BufferedReader(reader))
{
String line = null;
// 采用循环方式来一行一行的读取
while ((line = br.readLine()) != null)
{
// 如果读取的字符串为"exit",程序退出
if (line.equals("exit"))
{
System.exit();
}
// 打印读取的内容
System.out.println("输入内容为:" + line);
}
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
}

15.4.4 推回输入流

PushbackInputStream和PushbackReader

用unread方法将内容推回到缓冲区,从而允许重复读取刚刚读取的内容.

使用推回流,输出某分割符号之前的内容。但其实完全不必这么做,读出来判断就好了。

public static void pushbackTest() {
try(
// 创建一个PushbackReader对象,指定推回缓冲区的长度为64
PushbackReader pr = new PushbackReader(new FileReader("a.txt") , ))
{
char[] buf = new char[];
// 用以保存上次读取的字符串内容
String lastContent = "";
int hasRead = ;
// 循环读取文件内容
while ((hasRead = pr.read(buf)) > )
{
// 将读取的内容转换成字符串
String content = new String(buf , , hasRead);
int targetIndex = ;
// 将上次读取的字符串和本次读取的字符串拼起来,
// 查看是否包含目标字符串, 如果包含目标字符串
if ((targetIndex = (lastContent + content)
.indexOf("测试")) > )
{
// 将本次内容和上次内容一起推回缓冲区
pr.unread((lastContent + content).toCharArray());
// 重新定义一个长度为targetIndex的char数组
if(targetIndex > )
{
buf = new char[targetIndex];
}
// 再次读取指定长度的内容(就是目标字符串之前的内容)
pr.read(buf , , targetIndex);
// 打印读取的内容
System.out.print(new String(buf , ,targetIndex));
System.exit();
}
else
{
// 打印上次读取的内容
System.out.print(lastContent);
// 将本次内容设为上次读取的内容
lastContent = content;
}
}
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
}

system类里提供了三个重定向标准输入输出的方法。

setErr(PrintStream err)

setIn(InputStream in)

setOut(PrintStream out)

程序可通过重定向标准输出流,将System.out的输出重定向到文件输出.

15.6 Java虚拟机读写其他进程的数据

使用Runtime对象的exec()方法可以运行平台上的其他程序,该方法产生一个Process对象,Process对象代表由该Java程序启动的子进程.Process类提供了如下三个方法,用于让程序和其子进程进行通信.

InputStream getErrorStream():获取子进程的错误流,

InputStream getInputStream(): 获取子进程的输入流.

OutputStream getOutputStream(): 获取子进程的输出流.

这里的输入流和输出流是相对于该java程序(注意,不是子程序)而言的.这里的子进程相当于物理节点

注意,这里用的是getErrorStream(),因为这不是子进程向本进程传递的数据,所以属于其他,要用ErrorStream

public static void readFromProcess() throws IOException {
// 运行javac命令,返回运行该命令的子进程
Process p = Runtime.getRuntime().exec("java -version");
try(
// 以p进程的错误流创建BufferedReader对象
// 这个错误流对本程序是输入流,对p进程则是输出流
BufferedReader br = new BufferedReader(new
InputStreamReader(p.getErrorStream())))
{
String buff = null;
// 采取循环方式来读取p进程的错误输出
while((buff = br.readLine()) != null)
{
System.out.println(buff);
}
}
}
java version "1.8.0_51"
Java(TM) SE Runtime Environment (build 1.8.0_51-b16)
Java HotSpot(TM) -Bit Server VM (build 25.51-b03, mixed mode)

java两个程序之间传递信息:这端代码我没跑起来,待研究

public class WriteToProcess
{
public static void main(String[] args)
throws IOException
{
// 运行java ReadStandard命令,返回运行该命令的子进程
Process p = Runtime.getRuntime().exec("java ReadStandard");
try(
// 以p进程的输出流创建PrintStream对象
// 这个输出流对本程序是输出流,对p进程则是输入流
PrintStream ps = new PrintStream(p.getOutputStream()))
{
// 向ReadStandard程序写入内容,这些内容将被ReadStandard读取
ps.println("普通字符串");
ps.println(new WriteToProcess());
}
}
}
// 定义一个ReadStandard类,该类可以接受标准输入,
// 并将标准输入写入out.txt文件。
class ReadStandard
{
public static void main(String[] args)
{
try(
// 使用System.in创建Scanner对象,用于获取标准输入
Scanner sc = new Scanner(System.in);
PrintStream ps = new PrintStream(
new FileOutputStream("out.txt")))
{
// 增加下面一行将只把回车作为分隔符
sc.useDelimiter("\n");
// 判断是否还有下一个输入项
while(sc.hasNext())
{
// 输出输入项
ps.println("键盘输入的内容是:" + sc.next());
}
}
catch(IOException ioe)
{
ioe.printStackTrace();
}
}
}

15.7 RandomAccessFile

RandomAccessFile可以自由访问文件的任意位置,所以如果只需要访问文件部分内容,而不是把文件从头读到尾,使用RamdomAccessFile将是更好的选择.但是局限是,它只能读写文件,不能读写其他IO节点.

getFilePointer():返回文件记录指针的当前位置

seek(long pos):将文件记录指针定位到pos位置

public static void randomAccessFileTest(){
try(
RandomAccessFile raf = new RandomAccessFile(
"newFile.txt" , "r"))
{
// 获取RandomAccessFile对象文件指针的位置,初始位置是0
System.out.println("RandomAccessFile的文件指针的初始位置:"
+ raf.getFilePointer());
// 移动raf的文件记录指针的位置
raf.seek();
byte[] bbuf = new byte[];
// 用于保存实际读取的字节数
int hasRead = ;
// 使用循环来重复“取水”过程
while ((hasRead = raf.read(bbuf)) > )
{
// 取出“竹筒”中水滴(字节),将字节数组转换成字符串输入!
System.out.print(new String(bbuf , , hasRead ));
}
}
catch (IOException ex)
{
ex.printStackTrace();
}
}

RandomAccessFile 依然不能向文件的指定位置插入内容,如果直接将文件记录指针移动到中间某位置后开始输出,则新输出的内容会覆盖文件中原有的内容,如果需要向指定位置插入内容,程序需要先把插入点后面的内容读入缓冲区,等把需要插入的数据写入文件后,再将缓冲区的内容追加到文件的后面.

public static void insert(String fileName , long pos
, String insertContent) throws IOException
{
File tmp = File.createTempFile("tmp" , null);
tmp.deleteOnExit();
try(
RandomAccessFile raf = new RandomAccessFile(fileName , "rw");
// 使用临时文件来保存插入点后的数据
FileOutputStream tmpOut = new FileOutputStream(tmp);
FileInputStream tmpIn = new FileInputStream(tmp))
{
raf.seek(pos);
// ------下面代码将插入点后的内容读入临时文件中保存------
byte[] bbuf = new byte[];
// 用于保存实际读取的字节数
int hasRead = ;
// 使用循环方式读取插入点后的数据
while ((hasRead = raf.read(bbuf)) > )
{
// 将读取的数据写入临时文件
tmpOut.write(bbuf , , hasRead);
}
// ----------下面代码插入内容----------
// 把文件记录指针重新定位到pos位置
raf.seek(pos);
// 追加需要插入的内容
raf.write(insertContent.getBytes());
// 追加临时文件中的内容
while ((hasRead = tmpIn.read(bbuf)) > )
{
raf.write(bbuf , , hasRead);
}
}
}

如果仅仅是追加内容,就简单多了

public static void main(String[] args)
{
try(
//以读、写方式打开一个RandomAccessFile对象
RandomAccessFile raf = new RandomAccessFile("out.txt" , "rw"))
{
//将记录指针移动到out.txt文件的最后
raf.seek(raf.length());
raf.write("追加的内容!\r\n".getBytes());
}
catch (IOException ex)
{
ex.printStackTrace();
}
}

15.8 对象序列化(serialize)

对象的序列化指将一个java对象写入IO流中,与此对应的是,对象的反序列化(Deserialize)则指从IO流中恢复该java对象.

如果需要让某个对象支持序列化机制,那么必须让它的类是可序列化的,必须实现如下两个接口之一

Serializable

Externalizable

程序创建的每个JavaBean类都要实现Serializable

public static void writeObject() {
try (ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("obj.txt"));)
{
LearnIO learnIO = new LearnIO("");
oos.writeObject(learnIO); } catch (IOException ex) {
// TODO: handle exception
ex.printStackTrace();
}
} //但是,如果如下

LearnIO learnIO = new LearnIO("12334444444");


oos.writeObject(learnIO);

learnIO.test="abcdetc";

//不会写入abcdetc,因为不会序列化号码相同的东西
oos.writeObject(learnIO);

反序列化

public static void readObject(){
try(
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("obj.txt"));
){
LearnIO learnIO = (LearnIO)ois.readObject();
System.out.println(learnIO.test);
}catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}

反序列化机制无须通过构造器来初始化java对象.

如果使用序列化机制向文件中写入多个Java对象,使用反序列化机制恢复对象时必须按实际写入的顺序读取.

当一个可序列化类有多个父类时(包括直接父类和间接父类),这些父类要么有无参数的构造器,要么也是可序列化的--否则反序列化时将抛出InvalidClassException异常.如果父类是不可序列化的,只是带有无参数的构造器,则该父类中定义的成员变量值不会序列化到二进制流中.

15.8.3 对象引用的序列化

如果成员变量是引用类型,那么这个引用类型的类必须是可序列化的.

属于递归序列化

有static修饰和transient修饰的变量不会被序列化

15.8.4 自定义序列化

在实例变量前面使用transient关键字修饰,可以指定java序列化时无须理会该实例变量.

更详细的自定义序列化方法是重写writeObject和readObject方法.

15.8.5 另一种自定义序列化机制

实现Externalizable

java8--IO(java疯狂讲义3复习笔记)的更多相关文章

  1. java8--类加载机制与反射(java疯狂讲义3复习笔记)

    本章重点介绍java.lang.reflect包下的接口和类 当程序使用某个类时,如果该类还没有被加载到内存中,那么系统会通过加载,连接,初始化三个步骤来对该类进行初始化. 类的加载时指将类的clas ...

  2. java8--NIO(java疯狂讲义3复习笔记)

    NIO采用内存映射文件的方式处理输入输出,NIO将文件或文件的一段区域映射到内存中,这样就可以像访问内存一样来访问文件了(这种方式模拟了操作系统上的虚拟内存的概念),通过这种方式来进行输入输出比传统的 ...

  3. java8--网络编程(java疯狂讲义3复习笔记)

    重点复习一下网络通信和代理 java的网络通信很简单,服务器端通过ServerSocket建立监听,客户端通过Socket连接到指定服务器后,通信双方就可以通过IO流进行通信. 需要重点看的工具类:I ...

  4. java8--异常处理(java疯狂讲义3复习笔记)

    try,catch,finally,throw,throws java将异常分为两种,Checked异常和Runtime异常. IndexOutOfBoundsException NumberForm ...

  5. java8--Mysql数据库与JDBC编程(java疯狂讲义3复习笔记)

    JDBC:java database connectivity 数据库基本命令: 启动 show databases; create database [if not exists] 数据库名; do ...

  6. java8--多线程(java疯狂讲义3复习笔记)

    多线程这块,平时用的框架里都封装好了,只有写批处理和工具包时用过几次.现在水平仅仅限于会用的程度,需要全面深入学习多线程. 主要内容:创建线程,启动线程,控制线程,多线程的同步,线程池,使用线程安全的 ...

  7. java8--IO工具类(java疯狂讲义3复习笔记)

    Paths类 public static void pathTest(){ Path path = Paths.get("~"); System.out.println(path) ...

  8. 参考《Java疯狂讲义》

    参考<Java疯狂讲义>Lambda表达式支持将代码块作为方法参数,Lambda表达式允许使用更简洁的代码来创建只有一个抽象方法的接口(这种接口被称为函数式接口)的实例 1. Lambda ...

  9. java程序设计基础篇 复习笔记 第一单元

    java语言程序设计基础篇笔记1. 几种有名的语言COBOL:商业应用FORTRAN:数学运算BASIC:易学易用Visual Basic,Delphi:图形用户界面C:汇编语言的强大功能和易学性,可 ...

随机推荐

  1. java.sql.SQLException: Data truncated for column 'lastSeason' at row 1

    在使用项目将数据存储到 datetime 的字段 ,抛出了这个异常 而我是使用Java.util.Date 存储过去的 解决代码如下: Date date = new Date(); demo.set ...

  2. laravel 文件删除

    删除文件 <?php class demo{ public function del(){ $disk = Storage::disk('public');//获取磁盘实例 $disk-> ...

  3. Oracle常用内置数据表查询

    Oracle 查询库中所有表名.字段名.字段名说明,查询表的数据条数.表名.中文表名. 查询所有表名:select t.table_name from user_tables t;查询所有字段名:se ...

  4. iOS-runtime-根据类名推送到任意控制器,且实现属性传值

    // // WJRuntime.m // RuntimeSkip // // Created by tqh on 15/9/8. // Copyright (c) 2015年 tqh. All rig ...

  5. [luoguP3068] [USACO13JAN]派对邀请函Party Invitations(stl大乱交)

    传送门 记录每一个编号在那些组中,可以用vector,这里选择链式前向星. 每一组用set 将被邀请的放到queue中 #include <set> #include <queue& ...

  6. hdu 1325数据弱

    #include<stdio.h>//判断是否有环,判断是否有点,判断是否是一个父节点 #include<string.h> #define N 1000000 int pre ...

  7. bzoj3142[Hnoi2013]数列 组合

    Description 小 T最近在学着买股票,他得到内部消息:F公司的股票将会疯涨.股票每天的价格已知是正整数,并且由于客观上的原因,最多只能为N.在疯涨的K天中小T观察 到:除第一天外每天的股价都 ...

  8. Android应用的权限配置和权限列表

    权限配置写在Mainifest.xml文件中: <?xml version="1.0" encoding="utf-8"?> <manifes ...

  9. 【HDOJ6318】Swaps and Inversions(树状数组)

    题意: 给定一串数组,其中含有一个逆序对则需要花费x,交换相邻两个数需要花费y,输出最小花费. n<=1e5,-1e9<=a[i]<=1e9 思路: #include<cstd ...

  10. BZOJ1583: [Usaco2009 Mar]Moon Mooing 哞哞叫

    给n<=4000000,c,a1,b1,c1,a2,b2,c2,以c为初始得到的数,每次可以把得到的某个数x进行操作f1(x)=a1*x/c1+b1,f2(x)=a2*x/c2+b2,求最后能得 ...