说明
- 本文总结了上课Java老师的讲解,记录了一些经典的java用法
- 本文篇幅较长,没有耐心与兴趣的朋友勿入
I/O流的概念
-
流(stream)
Java采用流的概念屏蔽了存储数据的起点和终点种类,文件、键盘、网络和其他设备都可以把它们抽象为流,通过流可以自由地控制文件、内存、I/O设备等数据的流向
-
流的分类
- 根据I/O流的流向可分为输入流(inputstream)和输出流(outputsteam)
- 当程序读取数据时,开启了一个通向起点数据源的输入流,这个起点可以是文件、内存、网络连接。
- 当程序写入数据时,开启了一个通向目的地的输出流。
-
读写数据的方法基本遵循步骤
- 打开一个流 (I/O流一旦被创建后,就会自动打开)
- 读(写)信息
- 关闭流
I/O流的种类
-
字节流(byte oriented stream)
- 字节流以8位的字节为基本处理单位
- 字节流不能直接处理Unicode字符
-
字符流(byte oritented stream)
- 字符流以16位的字节为基本处理单位
- 字符流处理的单元为16位的Unicode字符,由Java虚拟机将字节转化为16位的Unicode字符
适用范围
- 字节流
- 所有文件的存储都是字节(byte)的存储,因此字节流可用于任何类型的对象,如音频文件、图片、歌曲
- 字符流
- 处理多国语言,就得用字符流
- 字符流通常处理文本
详细
一、文件File类
-
文件类的方法
File 类是 java.io 包中唯一代表磁盘文件本身的对象,也就是说,如果希望在程序中操作文件和目录,则都可以通过 File 类来完成。
File 类定义了一些方法来操作文件,如新建、删除、重命名文件和目录等。File 类不能访问文件内容本身,如果需要访问文件内容本身,则需要使用输入/输出流。
方法名称 | 说明 |
---|---|
boolean canRead() | 测试应用程序是否能从指定的文件中进行读取 |
boolean canWrite() | 测试应用程序是否能写当前文件 |
boolean delete() | 删除当前对象指定的文件 |
boolean exists() | 测试当前 File 是否存在 |
String getAbsolutePath() | 返回由该对象表示的文件的绝对路径名 |
String getName() | 返回表示当前对象的文件名或路径名(如果是路径,则返回最后一级子路径名) |
boolean createNewFile() | 创建一个新的文件。 |
boolean isAbsolute() | 当前 File 对象表示的文件是否为一个绝对路径名。 |
boolean isDirectory() | 测试当前 File 对象表示的文件是否为一个路径 |
boolean isFile() | 当前 File 对象表示的文件是否为一个“普通”文件 |
long lastModified() | 返回当前 File 对象表示的文件最后修改的时间 |
long length() | 返回当前 File 对象表示的文件长度 |
String[] list() | 返回当前 File 对象指定的路径文件列表 |
String[] list(FilenameFilter) | 返回当前 File 对象指定的目录中满足指定过滤器的文件列表 |
boolean mkdir() | 创建一个目录,它的路径名由当前 File 对象指定 |
boolean mkdirs() | 创建一个目录,它的路径名由当前 File 对象指定 |
boolean renameTo(File) | 将当前 File 对象指定的文件更名为给定参数 File 指定的路径名 |
-
文件类举例
(1)在磁盘上创建一个文件,先创建文件夹,再创建文件。
public class MyFileDemo {
public static void main(String args[]) {
String path = "d:"+File.separator+"filetest";
File filePath = new File(path);
if (filePath.exists()) {
filePath.delete();
}
filePath.mkdir();
File file = new File(path+File.separator+"test.txt");
if (file.exists()) {
file.delete();
}
try {
file.createNewFile();
System.out.println("创建文件成功!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
(2)遍历一个文件夹
public class ListAllFile {
public static void main(String[] args) {
String path = "e://360Downloads";
File file = new File(path);
showAllFile(file);
}
private static void showAllFile(File file) {
if (file.isDirectory()) {//如果是目录
System.out.println("文件夹:" + file.getName());
File[] listFiles = file.listFiles();//获取当前路径下的所有文件和目录,返回File对象数组
for (File f : listFiles) {//将目录内的内容对象化并遍历
showAllFile(f);
}
}
else if(file.isFile()) {//如果是文件
System.out.println("文件:" + file.getName());
}
}
}
二、输入输出流
-
实例:用字节流把数据写入文件和读到内存中。
public class InptutAndOutDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
String data="jiava计算机";
File file=new File("D:"+File.separator+"test.txt");
writeDataToFile(file,data);
readFromFile(file);
}
private static void readFromFile(File file) {
// TODO Auto-generated method stub
InputStream inputStream=null;
try {
inputStream = new FileInputStream(file);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int flen = (int) file.length();
byte[] b = new byte[flen];
int len =0;
try {
len = inputStream.read(b);
}catch (IOException e1){
e1.printStackTrace();
}finally {
try {
inputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(len);
System.out.print(new String(b));
}
private static void writeDataToFile(File file, String data) {
// TODO Auto-generated method stub
OutputStream outputStream=null;
try {
outputStream=new FileOutputStream(file);
outputStream.write(data.getBytes());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally {
try {
outputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
三、字符输入输出流举例
字符流只能操作文本文件,不能操作图片,视频等非文本文件(因为是二进制存储的,要用字节流)
- 字符输出流(Writer)
public abstract class Writer是用于写出字符流的所有类的超类,是一个抽象类,它定义了字节输出流的基本共性能方法
方法名称 | 说明 |
---|---|
void write(int c) | 写入单个字符 |
void write(char[] cbuf) | 写入字符数组 |
abstract void write(char[] cbuf, int off, int len) | 写入字符数组的某一部分 |
void write(String str) | 写入字符串 |
void write(String str, int off, int len) | 写入字符串的某一部分 |
void flush() | 刷新该流的缓冲 |
- FileWriter类是写字符到文件的类,构造时使用系统默认的字符编码和默认字节缓冲区。
方法名称 | 说明 |
---|---|
FileWriter(File file) | 根据给定的 File 对象构造一个 FileWriter 对象 |
FileWriter(File file, boolean append) | 根据给定的 File 对象构造一个 FileWriter 对象。其中append参数代表是否追加 |
FileWriter(String fileName) | 根据给定的文件名构造一个 FileWriter 对象 |
FileWriter(String fileName, boolean append) | 根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象 |
- 字符输入流
Reader 类是所有字符流输入类的父类,该类定义了许多方法,这些方法对所有子类都是有效的。
方法名及返回值类型 | 说明 |
---|---|
int read() | 从输入流中读取一个字符,并把它转换为 0~65535 的整数。如果返回 -1, 则表示 已经到了输入流的末尾。为了提高 I/O 操作的效率,建议尽量使用下面两种 read() 方法 |
int read(char[] cbuf) | 从输入流中读取若干个字符,并把它们保存到参数 cbuf 指定的字符数组中。 该方 法返回读取的字符数,如果返回 -1,则表示已经到了输入流的末尾 |
int read(char[] cbuf,int off,int len) | 从输入流中读取若干个字符,并把它们保存到参数 cbuf 指定的字符数组中。其中, off 指定在字符数组中开始保存数据的起始下标,len 指定读取的字符数。该方法返 回实际读取的字符数,如果返回 -1,则表示已经到了输入流的末尾 |
Java 提供了用来读取字符文件的便捷类——FileReader。该类的构造方法有如下两种重载形式。
方法名称 | 说明 |
---|---|
FileReader(File file) | 在给定要读取数据的文件的情况下创建一个新的 FileReader 对象。其中,file 表示要从中读取数据的文件 |
FileReader(String fileName) | 在给定从中读取数据的文件名的情况下创建一个新 FileReader 对象。其中,fileName 表示要从中读取数据的文件的名称,表示的是一个文件的完整路径 |
举例:
public class ReaderAndWriterDemo {
public static void main(String[] args) throws IOException {
String data="jiava计算机";
File file=new File("D:"+File.separator+"test1.txt");
Writer writer=new FileWriter(file,true);//追加方式
writer.write("\r\n");
writer.write("你好!\r\n");
writer.write("我在学习!\r\n");
writer.flush();
writer.close();
//读数据
Reader reader=new FileReader(file);
int len=(int)file.length();
char myChar[]=new char[len];
int rlen = reader.read(myChar);
System.out.println(rlen);
System.out.println(new String(myChar));
reader.close();
}
}
四、Java缓冲输入输出流
为什么要缓冲输入输出流?由于I/O的速度和CPU的速度不匹配,导致文件的读取较慢。所以通过缓存,一次性将大量的数据刷入内存或者保存在本地上。提高文件的访问效率。
字节缓冲流: BufferedInputStream , BufferedOutputStream
字符缓冲流: BufferedReader , BufferedWriter
- 字节缓冲流的使用(复制文件)
public class CopyFileByBuffer {
public static void main(String[] args) {
File sourceFile=new File("d:"+File.separator+"filetest"+File.separator+"xx.zip");
File targetFile=new File("d:"+File.separator+"movie"+File.separator+"xx.zip");
long startTime = System.currentTimeMillis();
copyFileByBuffered(sourceFile,targetFile);
long endTime = System.currentTimeMillis();
System.out.println("缓冲流(默认缓冲区)复制时间:" + (endTime - startTime) + " 毫秒");
}
private static void copyFileByBuffered(File sourceFile, File targetFile) {
int b;
try {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(sourceFile),2048);
BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(targetFile),2048);
while((b=bis.read())!=-1) {
bos.write(b);
}
bis.close();
bos.flush();
bos.close();
}
catch(IOException e) {
e.printStackTrace();
}
}
}
- 字节缓冲流的使用(高效复制文件)
public class CopyFileByBufferMore {
public static void main(String[] args) {
File sourceFile=new File("d:"+File.separator+"filetest"+File.separator+"xx.zip");
File targetFile=new File("d:"+File.separator+"movie"+File.separator+"xx.zip");
long startTime = System.currentTimeMillis();
copyFileByBuffered(sourceFile,targetFile);
long endTime = System.currentTimeMillis();
System.out.println("缓冲流(默认缓冲区)复制时间:" + (endTime - startTime) + " 毫秒");
}
private static void copyFileByBuffered(File sourceFile, File targetFile) {
int b;
byte[] bytes=new byte[8*1024];
try {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(sourceFile),2048);
BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(targetFile),2048);
while((b=bis.read(bytes))!=-1) {
bos.write(bytes,0,b);
}
bis.close();
bos.flush();
bos.close();
}
catch(IOException e) {
e.printStackTrace();
}
}
}
- 使用字符缓冲流逐行读取文件。创建Student类
public class ReadFileByBuffered {
public static void main(String[] args) {
// TODO Auto-generated method stub
List<Student> list=new ArrayList<Student>();
File file=new File("d:"+File.separator+"filetest"+File.separator+"score.txt");
try {
BufferedReader br=new BufferedReader(new FileReader(file));
String line = null;
br.readLine();
String score[]=new String[7];
while((line=br.readLine())!=null) {
score=line.split("\\s+");
Student st=new Student();
for(int i=0;i<score.length;i++) {
st.setId(score[0]);
st.setName(score[1]);
st.setMath(Integer.parseInt(score[2]));
st.setChinese(Integer.parseInt(score[3]));
st.setEnglish(Integer.parseInt(score[4]));
st.setTotal(st.getMath()+st.getChinese()+st.getEnglish());
st.setAverage(st.getTotal()/3.0f);
}
list.add(st);
}
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for(Student st:list) {
System.out.println(st.getId()+" "+"\t"+st.getName());
}
}
}
五、对象序列化与对象输入输出流
Java中要实现将对象保存起来持久化,需要让对象实现Serializable接口,这样就能将java对象用二进制流保存并恢复。
public class SaveObject {
public static void main(String[] args) {
File fileName=new File("d:\\filetest\\obj.txt") ;
try {
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(fileName));
User user=new User(1,"张三",18,"男");
oos.writeObject(user);
oos.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//读取对象流
try {
ObjectInputStream ois=new ObjectInputStream(new FileInputStream(fileName));
try {
User user1=(User)ois.readObject();
System.out.println(user1.toString());
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
六、RandomAccessFile 类
RandomAccessFile 类支持 "随机访问" 的方式,程序可以直接跳到文件的任意地方来读、写文件。支持文件追加。RandomAccessFile 类支持字节和字符流。
方法 | 功能描述 |
---|---|
long length() | 返回文件长度 |
void seek(long pos) | 移动文件位置指示器,pos 指定从文件开头的偏离字节数 |
int skipBytes(int n) | 跳过 n 个字节,返回数为实际跳过的字节数 |
int read() | 从文件中读取一个字节,字节的高 24 位为 0,若遇到文件结尾,返回-1 |
final byte readByte() | 从文件中读取带符号的字节值 |
final char readChar() | 从文件中读取一个 Unicode 字符 |
final void writeChar(inte c) | 写入一个字符,两个字节 |
final void writeBytes(String s) | 写入个字符串 |
实例RandomAccessFile读写
private static void readFile(File file) {
// TODO Auto-generated method stub
try {
RandomAccessFile raf=new RandomAccessFile(file, "r");
String line=null;
raf.seek(0);
while((line=raf.readLine())!= null){
System.out.println(new String(line.getBytes("ISO-8859-1"),"gb2312"));
}
raf.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static void writeFile(File file) {
try {
RandomAccessFile raf=new RandomAccessFile(file, "rw");
long len=raf.length();
raf.seek(len);//在文件尾部写行
raf.write(("中午"+"\r\n").getBytes());;
raf.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
RandomAccessFile so=null;
RandomAccessFile ta=null;
try {
so=new RandomAccessFile("src\\myfile\\360qudong.exe","r");
ta=new RandomAccessFile("src\\myfile\\360qudong1.exe","rw");
byte b[]=new byte[1024];
int len;
while((len=so.read(b))!=-1){
ta.write(b,0,len);
}
System.out.println("0k");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
if(ta!=null){
try {
ta.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(so!=null){
try {
so.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
七、URL对象与输入输出流
URL全称是“统一资源定位”,表示的是网络上的某个文件。Java中URL类是用来操作网络中的资源文件。
- URL类的构造方法:
序号 | 方法描述 |
---|---|
1 | public URL(String protocol, String host, int port, String file) throws MalformedURLException. 通过给定的参数(协议、主机名、端口号、文件名)创建URL。 |
2 | public URL(String protocol, String host, String file) throws MalformedURLException 使用指定的协议、主机名、文件名创建URL,端口使用协议的默认端口。 |
3 | public URL(String url) throws MalformedURLException 通过给定的URL字符串创建URL |
4 | public URL(URL context, String url) throws MalformedURLException 使用基地址和相对URL创建 |
-
URL类的方法
URL类的方法很多,这里介绍openConnection()方法:
public URLConnection openConnection() throws IOException: 打开一个URL连接,并返回一个HttpURLConnection对象。
-
HttpURLConnection对象的方法
public InputStream getInputStream() throws IOException:返回URL的输入流,用于读取资源。
实例:程序下载网页中的图片
public static void main(String[] args) {
saveImage("https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png");
}
private static void saveImage(String str) {
URL url=null;
HttpURLConnection conn=null;
try {
url=new URL(str);
conn=(HttpURLConnection)url.openConnection();
conn.connect();
BufferedInputStream bis=new BufferedInputStream(conn.getInputStream());
BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("d:\\ddd.png"));
byte bt[]=new byte[1024];
int size;
while((size=bis.read(bt))!=-1) {
bos.write(bt,0,size);
}
System.out.println("finsh");
bos.flush();
bos.close();
bis.close();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}