https://edu.51cto.com/course/17347.html 湯小洋
基礎
1. 簡介
IO:Input Output 輸入和輸出流
- 通過IO流實現文件的輸入和輸出功能
- 用於對文件進行讀寫的操作
流stream:可以理解爲一組有順序的、有起點和終點的動態數據集合 - 文件是數據在硬盤上的靜態存儲
- 流是數據在傳輸時的動態形態
2. 文件的分類(兩類)
- 文本文件
可以使用記事本編輯的文件, .txt .java .properties - 二進制文件
除了文本文件,其他所有文件都是二進制文件
InputStream是字節輸入流的頂層父類,常用子類:
- FileInputStream
- ByteArrayInputStream
- ObjectInputStream
OutputStream是字節輸出流的頂層父類,常用子類: - FileOutputStream
- ByteArrayOutputStream
- ObjectOutputStream
3. 流的分類(三類)
按流的方向(站在Java程序的角度)
- 輸入流:用於讀取數據,比如從文件中讀取數據到程序中,由InputStream和Reader作爲父類
- 輸出流:用於寫出數據,比如將程序中的數據寫出到文件中,由OutputStream和Writer作爲父類
按流中數據的單位 - 字節流byte:所操作的最小數據單元爲字節,由InputStream和OutputStream作爲父類
- 字符流char:所操作的最小數據單元爲字符,由Reader和Writer作爲父類,
【一個英文字符佔1個字節,一個漢字佔2個字節(GBK) 或 3個字節(UTF8)】
按數據的來源 - 節點流:直接對數據源進行操作,如操作文件
- 包裝流:對一個節點流進行操作(包裝)
基礎API
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.Date;
public class Test01 {
public static void main(String[] args) throws URISyntaxException, IOException {
//java.io.File
/*
* 創建一個File對象
*/
// 方式1:指定文件的全路徑
// File file = new File("D:\\resource\\a.txt"); // 絕對路徑
// File file = new File("D:/resource/a.txt");
// File file = new File("/home/soft01/a.txt");
// File file = new File("a.txt"); //相對路徑
// 方式2:指定父目錄的路徑和文件名
// File file = new File("C:/resource", "code/a.txt");
// 方式3:指定父目錄的File對象和文件名
File file1 = new File(new File("C:/resource"), "code/a.txt");
System.out.println("file1=:"+file1);//C:\resource\code\a.txt
// 方式4:指定URI統一資源標識符
File file2 = new File( Test01.class .getClassLoader() // 獲取類加載器
.getResource("data.properties") // 加載類路徑下的文件(當然文件得存在),返回URL(UniformResource Locator統一資源定位符)
.toURI() // 轉換爲URI(Uniform Resource Identifier統一資源標識符)
);
System.out.println("file2=:"+file2);//C:\idea_pro\io\target\classes\data.properties
File file = new File("c.txt"); // 放在項目根目錄下才能找到,java默認是相對於項目的根目錄
System.out.println("文件名:"+file.getName());//文件名:c.txt
System.out.println("路徑名:"+file.getPath());//路徑名:c.txt
System.out.println("絕對路徑名:"+file.getAbsolutePath());//絕對路徑名:C:\idea_pro\io\c.txt
System.out.println("父目錄:"+file.getParent());//null
System.out.println("父目錄文件對象:"+file.getParentFile()); //null 返回的是File對象
System.out.println("文件長度:"+file.length()+"字節");//文件長度:10字節
System.out.println("最後一次修改時間:"+new Date(file.lastModified()));//Sun May 10 16:59:38 CST 2020 lastModified()返回的是long值
System.out.println("是否可讀:"+file.canRead());//是否可讀:true
System.out.println("是否可寫:"+file.canWrite());//是否可寫:true
System.out.println("是否爲普通文件:"+file.isFile());//是否爲普通文件:true
System.out.println("是否爲目錄:"+file.isDirectory());//是否爲目錄:false
System.out.println("是否爲隱藏文件:"+file.isHidden());//是否爲隱藏文件:false
System.out.println(file); //c.txt 直接輸出File對象,本質上就是調用getPath()
System.out.println(file.exists()); //true 判斷指定路徑的文件是否存在
/*
* 文件目錄的操作
*/
File file3 = new File("C:/resource/c.txt");
boolean isSuccess = file3.createNewFile(); // 創建一個空文件,返回一個boolean,表示成功或失敗
System.out.println("是否創建成功"+isSuccess);
file3.renameTo(new File("c2.txt")); //重命名 這裏是相對路徑會在項目根目錄下新建c2.txt文件
boolean isSuccess2 = file3.delete(); //刪除文件
System.out.println("刪除是否成功"+isSuccess2);
File f = new File("D:/software");
// boolean isSuccess = f.mkdir(); // 創建目錄,如果父目錄不存在 ,會導致創建失敗
// boolean isSuccess = f.mkdirs(); // 創建包括父目錄的目錄,即級聯創建
// System.out.println(isSuccess);
String[] names = f.list(); // 獲取目錄下的所有文件和目錄的名稱
System.out.println(Arrays.toString(names));
File[] files = f.listFiles(); // 獲取目錄下的所有文件和目錄的對象
System.out.println(Arrays.toString(files));
// 常量
System.out.println(File.separator);//當前系統分隔符
}
}
案例
遞歸獲取指定目錄下所有文件
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
public class Test01 {
public static void main(String[] args) throws URISyntaxException, IOException {
File file = new File("c:/idea_pro");
display(file);
}
public static void display(File file) {
// 判斷文件是否存在
if (!file.exists()) {
return;
}
// 判斷是否爲目錄
if (file.isDirectory()) {
File[] files = file.listFiles();
for (File f : files) {
if(f.isFile()){
System.out.println(f.getAbsolutePath());
}else{
display(f);
}
}
}else{
System.out.println(file.getAbsolutePath());
}
}
}
遞歸刪除全部空目錄
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
public class Test01 {
public static void main(String[] args) throws URISyntaxException, IOException {
File file = new File("d:/resource");
remove(file);
}
public static void remove(File file) {
// 判斷是否爲空目錄
if (file.isDirectory() && file.listFiles().length == 0) {
file.delete();
System.out.println("刪除空目錄:" + file.getAbsolutePath());
// 刪除當前目錄後可能導致父目錄也爲空,所以需要對父目錄進行處理
remove(file.getParentFile());
} else if (file.isDirectory()) {
// 如果當前目錄不爲空目錄,則獲取目錄下所有文件進行再處理
File[] files = file.listFiles();
for (File f : files) {
remove(f); // 遞歸刪除
}
}
}
}
FileInputStream 文件字節輸入流
import java.io.*;
import java.net.URISyntaxException;
public class Test01 {
public static void main(String[] args) throws URISyntaxException, IOException {
test01();
// test02();
// test03();
}
// 基本用法
public static void test01(){
FileInputStream fis = null;//不初始化時,close方法報錯,懷疑可能未初始化
try {
//fis = new FileInputStream("a.txt");
fis = new FileInputStream(new File("a.txt"));// 讀取項目根目錄下的文件
/*
int data = fis.read(); //處於阻塞狀態,讀取一個字節返回int類型的字節值,a就是97,讀取到末尾返回-1
while(data!=-1){
System.out.println((char)data);
data=fis.read();
}
*/
int data = -1;//初始值-1
while((data=fis.read()) != -1){
System.out.println(data+" : "+(char)data); // 字節流讀取中文時可能會出現亂碼(中文utf-8時是3個字節)
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally{
if(fis != null){ // 需要判斷是否爲null,防止出現NullPointerException
try {
fis.close(); // 關閉輸入流:只要是打開了外部的資源(文件\數據庫連接\網絡連接),在使用後都需要關閉,釋放資源
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
// 其他用法
public static void test02(){
// 在JDK7中,提供了一種新語法,叫做try-with-resource,能夠自動關閉外部資源,不需要寫finally,簡化代碼
try(
// 此處只能創建實現了AutoClosable接口的對象
FileInputStream fis=new FileInputStream("a.txt");
){
//System.out.println((char)fis.read());
//System.out.println(fis.available()); // 流中可讀取的字節數
byte[] buffer=new byte[1024*1024]; // 減少對硬盤的讀取次數,提高效率
// int num = fis.read(buffer); // 一次性讀取buffer.length個字節到buffer中,返回實際讀取到的字節數,如果讀取到末尾,則返回-1
// System.out.println(num);
// String str = new String(buffer);
// System.out.println(str);
//
// num = fis.read(buffer);
// System.out.println(num);
//System.out.println(new String(buffer, 0, num)); // 將指定長度的字節數組轉換爲字符串
int num=-1;
while((num=fis.read(buffer)) != -1){
System.out.println(new String(buffer,0,num));
}
}catch(IOException e){
e.printStackTrace();
}
}
// 加載不同路徑下的文件
public static void test03(){
try(
// 默認加載項目根路徑下
//InputStream is=new FileInputStream("a.txt");
// 加載classpath類路徑,即src目錄
//InputStream is=Test01_FileInputStream.class.getClassLoader().getResourceAsStream("b.txt");
// 加載當前類所在目錄
InputStream is=Test01.class.getResourceAsStream("c.txt");
){
System.out.println((char)is.read());
System.out.println("加載文件成功!");
}catch(IOException e){
e.printStackTrace();
}
}
}
FileOutputStream 文件字節輸入流
import java.io.*;
public class Test01 {
public static void main(String[] args) {
FileOutputStream fos = null;
try {
// 如果文件不存在,會自動創建文件,如果文件存在,默認會覆蓋原文件的內容
// fos=new FileOutputStream("a.txt");
fos = new FileOutputStream("a.txt", true); // true表示以追加的形式寫數據
byte[] data = "hello world".getBytes();
fos.write(data); // 寫入數據,只是將數據寫入到內存的緩衝區中,並沒有真正寫入到文件中
fos.flush(); // 刷新輸出流,完成數據的輸出,當關閉流時會自動調用該方法
System.out.println("寫入數據成功");
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
單個文件複製
import java.io.*;
public class Test01 {
public static void main(String[] args) {
// 如果文件不存在,會自動創建文件,如果文件存在,默認會覆蓋原文件的內容
// test01();
test02();
}
/*
* 每次複製一個字節 read()方法默認讀取一個字節
*/
public static void test01(){
InputStream is = null;
OutputStream os = null;
try {
is = new FileInputStream("a.txt");
os = new FileOutputStream("aa.txt");
int data=-1;
while((data=is.read())!=-1){
os.write(data); // 讀一個字節,寫一個字節
}
System.out.println("文件複製成功");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
if(os!=null){
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(is!=null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/*
* 每次複製多個字節 read(arg)方法默認讀取指定參數個字節
*/
public static void test02(){
try(
InputStream is = new FileInputStream("C:\\software\\oss-browser-win32-x64\\oss-browser.exe");
OutputStream os = new FileOutputStream("oss.exe");
){
byte[] buffer = new byte[1024*1024];
int num = -1;
while((num=is.read(buffer)) != -1){
os.write(buffer, 0, num);
}
System.out.println("文件複製成功");
}catch(IOException e){
e.printStackTrace();
}
}
}
複製目錄下所有文件到目標目錄
import java.io.*;
public class Test01 {
public static void main(String[] args) {
copyFile("C:/software","c:/backup");
}
public static void copyFile(String srcPath, String destPath) {
File srcFile = new File(srcPath);
File destFile = new File(destPath);
if(srcFile.isDirectory()){
destFile=new File(destPath+File.separator+srcFile.getName());
destFile.mkdirs();
File[] files = srcFile.listFiles();
for (File file : files) {
copyFile(file.getAbsolutePath(), destFile.getAbsolutePath());
}
}else if(srcFile.isFile()){
try(
InputStream is=new FileInputStream(srcFile);
OutputStream os=new FileOutputStream(destPath+File.separator+srcFile.getName());
){
byte[] buffer=new byte[1024*1024];
int num=-1;
while((num=is.read(buffer))!=-1){
os.write(buffer, 0, num);
}
System.out.println("複製"+srcPath);
}catch(IOException e){
e.printStackTrace();
}
}
}
}
字節數組輸入輸出流
import java.io.*;
public class Test01 {
public static void main(String[] args) {
// 流(數據)的來源或目的地並不一定是文件,也可以是內存中的一塊空間,例如一個字節數組
// ByteArrayInputStream 字節數組輸入流:從字節數組中讀取數據,即將字節數組當作流輸入的來源
// ByteArrayOutputStream 字節數組輸出流:將數據寫出到內置的字節數組中,即將字節數組當作流輸出的目的地
test01();
test02();
}
// ByteArrayInputStream
public static void test01(){
byte[] data="welcome to java".getBytes();
try {
// 定義字節數組輸入流,數據來源爲字節數組
InputStream is = new ByteArrayInputStream(data);
int i=-1;
while((i=is.read())!=-1){
System.out.print((char)i);
}
//輸出welcome to java
} catch (IOException e) {
e.printStackTrace();
}
/*
* ByteArrayInputStream和ByteArrayOutputStream不需要關閉
* 因爲其操作的是內存中的字節數組,屬於內存讀寫流,並非操作的外部資源
*/
}
// ByteArrayOutputStream
public static void test02(){
try {
ByteArrayOutputStream os = new ByteArrayOutputStream();
// 將數據寫出到內置的字節數組中
os.write("hello".getBytes());
os.flush();
// 獲取內置的字節數組中的數據
byte[] buffer = os.toByteArray();
System.out.println(new String(buffer));//hello
System.out.println(os.toString());//hello
} catch (IOException e) {
e.printStackTrace();
}
}
}
對象輸入輸出流
如果希望將Java對象寫入到IO流中,或從IO流中讀取Java對象,則要使用對象輸入輸出流,稱爲對象的序列化和反序列化
4.1 序列化和反序列化
序列化:將Java對象寫入IO流中,實現將對象保存在磁盤上或在網絡中傳遞對象
反序列化:從IO流中讀取Java對象,實現從磁盤上或網絡中恢復對象
要求:
對象必須實現Serializable接口,才能被序列化,轉換爲二進制流,通過網絡進行傳輸
通過 serialVersionUID 判斷對象的序列化版本的一致性:
在反序列時,會將流中的serialVersionUID與本地相應實體對象/類的serialVersionUID進行比較
如果相同就認爲版本一致,則可以進行反序列化
如果不相同,則會出現序列化版本不一致的異常InvalidClassException
4.2 ObjectInputStream
對象輸入流:用來讀取對象,即反序列化
ObjectInputStream 和 ObjectOutputStream 屬於包裝流(用於對節點流進行功能擴展 / 包裝)
在創建包裝流,需要傳入要操作的節點流對象
當關閉流時,只需要關閉包裝流,被包裝的節點流也會被關閉
4.3 ObjectOutputStream
對象輸出流:用來寫入對象,即序列化
User.java
import java.io.Serializable;
public class User implements Serializable {
// static final long serialVersionUID
// 根據類名、接口名、成員方法和屬性等生成的一個64位的哈希值
// 表示對象類型的的唯一標識
private static final long serialVersionUID = 705661196096434175L;
private Integer id; // 都使用包裝類型,默認爲null
private String name;
private transient Integer age; // transient修飾的屬性不會被序列化(static變量也不會被序列化)
private Address address; // 對象屬性也必須實現Serializable接口
public User(Integer id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}
Address.java
import java.io.Serializable;
public class Address implements Serializable {
private String province;
private String city;
public Address() {
super();
}
public Address(String province, String city) {
super();
this.province = province;
this.city = city;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
@Override
public String toString() {
return "Address [province=" + province + ", city=" + city + "]";
}
}
Test.java
import java.io.*;
import java.util.Arrays;
import java.util.List;
public class Test01 {
public static void main(String[] args) {
test01();
test02();
}
// 序列化,寫入對象
public static void test01() {
User u1 = new User(1001, "tom", 18);
u1.setAddress(new Address("江蘇", "南京"));
User u2 = new User(1002, "jack", 21);
u1.setAddress(new Address("江蘇", "揚州"));
List<User> users = Arrays.asList(u1, u2);
ObjectOutputStream oos = null;
try {
// FileOutputStream fos = new FileOutputStream("user.data");
// oos = new ObjectOutputStream(fos);
//輸出到user.data文件中,是二進制文件,文本編輯器打開不能正常顯示
oos = new ObjectOutputStream(new FileOutputStream("user.data"));
// 寫入對象
// oos.writeObject(u1);
// oos.writeObject(u2);
oos.writeObject(users);
oos.flush();//這裏不flush也行,後面有close
System.out.println("寫入對象成功");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (oos != null) {
try {
oos.close(); // 只需要關閉包裝流
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
// 反序列化,讀取對象
public static void test02() {
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new FileInputStream("user.data"));
// 讀取順序和寫入順序一致
// User u1 = (User) ois.readObject();
// User u2 = (User) ois.readObject();
// System.out.println(u1);
// System.out.println(u2);
List<User> list = (List<User>) ois.readObject();
System.out.println(list);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
if (ois != null) {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
文件的拆分和合並
import java.io.*;
public class Test01 {
public static void main(String[] args) {
// 路徑不包含bak的話報錯,不知爲何,總之不能在根目錄下操作
splitFile("C:\\bak\\oss.zip");
mergeFile("C:\\bak\\oss.zip_1");
}
// 拆分文件:一個輸入流,多個輸出流
public static void splitFile(String filePath) {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream(filePath);
byte[] buffer = new byte[1024 * 1024 * 10]; // 每次讀取10M
int num = -1;
int index = 0;
while ((num = fis.read(buffer)) != -1) {
fos = new FileOutputStream(filePath + "_" + (++index));
fos.write(buffer, 0, num);
fos.flush();
fos.close();
}
System.out.println("拆分成功,共拆分爲:" + index + "個");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
// 合併文件:一個輸出流,多個輸入流
public static void mergeFile(String filePath) { //filePath只需要一個文件名,通過截取即可
String basePath = filePath.substring(0, filePath.lastIndexOf("_"));
FileOutputStream fos = null;
FileInputStream fis = null;
try {
fos = new FileOutputStream(basePath);
int index = 1;
File f = null;
while ((f = new File(basePath + "_" + index++)).exists()) {
fis = new FileInputStream(f);
byte[] buffer = new byte[fis.available()];
fis.read(buffer);
fos.write(buffer);
fos.flush();
fis.close();
}
System.out.println("合併成功:"+basePath);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
文件字符流
import java.io.*;
public class Test01 {
public static void main(String[] args) {
/*
* FileReader、FileWriter的用法與FileInputStream、FileOutputStream類似
* 前者是以字符爲單位,後者是以字節爲單位
*/
try(
Reader reader=new FileReader("User.java"); // 字符流無法讀寫二進制文件,
Writer writer = new FileWriter("User2.java")
){
//int data = reader.read(); // 每次讀取一個字符,返回int類型的字符值
//System.out.println((char)data);
char[] buffer=new char[5];
int num = -1;
while((num=reader.read(buffer))!=-1){
writer.write(buffer, 0, num);
}
System.out.println("複製文件成功");
}catch(IOException e){
e.printStackTrace();
}
}
}
字符緩衝輸入輸出流 打印流
包裝流 BufferedReader PrintWriter
import java.io.*;
public class Test01 {
public static void main(String[] args) {
try(
BufferedReader reader = new BufferedReader( new FileReader("a.txt") );
//BufferedWriter writer = new BufferedWriter(new FileWriter("aaaa.txt"));
PrintWriter writer = new PrintWriter("aaaa.txt");
){
//String data = reader.readLine(); // 每次讀取一次,讀不到數據時返回null
//System.out.println(data);
String data = null;
while((data = reader.readLine()) != null){
//writer.write(data);
//writer.newLine(); //插入換行符
//writer.write("\r\n"); // 也可以插入\r\n進行換行
writer.println(data); // 寫入並換行,更方便
}
System.out.println("複製文件成功");
}catch(IOException e){
e.printStackTrace();
}
}
}
轉換流
- 用於將字節流轉換爲字符流,同時可以實現編碼的轉換
- 在轉換時需要指定使用的字符集,如果不指定默認使用JVM的字符集
- 在Java中沒有提供將字符流轉換爲字節流的方法,不支持該操作
InputStreamReader
將字節輸入流轉換爲字符輸入流(InputStream - Reader)
OutputStreamWriter
將字節輸出流轉換字符輸出流(OutputStream - Writer)
public class Test03_轉換流 {
public static void main(String[] args) {
try(
// FileInputStream fis = new FileInputStream("a.txt");
// InputStreamReader isr = new InputStreamReader(fis, "gbk");
// BufferedReader reader=new BufferedReader(isr);
BufferedReader reader=new BufferedReader(
new InputStreamReader( new FileInputStream("b.txt") ,"gbk") // 以gbk編碼讀取文件
);
// BufferedReader reader = new BufferedReader(new InputStreamReader
// (Test03_轉換流.class.getClassLoader().getResourceAsStream("b.txt")));
// BufferedWriter writer=new BufferedWriter(
// new OutputStreamWriter(
// new FileOutputStream("c.txt")
// ,"utf-8") // 以utf-8編碼寫入文件
// );
PrintWriter writer = new PrintWriter("c.txt", "utf-8"); // 這個最強大
){
// System.out.println(reader.readLine());
writer.write(reader.readLine());
System.out.println("複製文件成功");
}catch(IOException e){
e.printStackTrace();
}
}
}
RandomAccessFile
隨機讀寫流,是一個字節流,可以對文件進行隨機讀寫
- 隨機:可以定位到文件的任意位置進行讀寫操作,通過移動指針(Pointer)來實現
- 讀寫:使用該流既能讀取文件,也能寫入文件
public class Test {
public static void main(String[] args) {
try(
/*
* 當文件不存在時:
* 如果模式爲r,會報異常FileNotFoundException
* 如果模式爲rw,會自動創建文件
*/
RandomAccessFile raf=new RandomAccessFile("x.txt", "rw"); //模式:r只讀、rw讀寫
){
System.out.println(raf.getFilePointer()); // 獲取當前指針的位置,從0開始
raf.write("張三".getBytes()); //對於utf-8,一個漢字佔3個字節
raf.write("hello".getBytes());
System.out.println(raf.getFilePointer()); // 11
System.out.println("寫入成功");
raf.seek(8); // 將指針移動到指定的位置
raf.write("李四".getBytes());
System.out.println(raf.getFilePointer()); // 14
raf.seek(6);
byte[] buffer = new byte[2];
raf.read(buffer);
System.out.println(new String(buffer));
System.out.println(raf.getFilePointer()); // 8
raf.skipBytes(3); // 將指針向後跳過指定的字節,只能往前,不能倒退 ——>
buffer = new byte[1024*1024];
int num = -1;
while((num = raf.read(buffer)) != -1){
System.out.println(new String(buffer,0,num));
}
// 修改數據
raf.seek(8);
raf.write("趙".getBytes());
System.out.println("修改成功");
}catch(IOException e){
e.printStackTrace();
}
}
}
文件的加密
* 實現文件的加密
* a.txt ——> a.txt.sec
*
* 思路:讀取文件中的每個字節,與pwd進行異或的操作
*/
import java.io.*;
import java.util.Scanner;
public class Test01 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("請輸入文件路徑:");
String filePath=input.nextLine();
System.out.print("請輸入密碼:");
int pwd = input.nextInt();
secret(filePath, pwd);
System.out.println("加密成功");
}
public static void secret(String filePath, int pwd){
try(
FileInputStream fis=new FileInputStream(filePath);
FileOutputStream fos = new FileOutputStream(filePath+".sec");
){
int data=-1;
while((data=fis.read())!=-1){
fos.write(data ^ pwd);
}
}catch(IOException e){
e.printStackTrace();
}
}
}