Java第09次實驗(IO流) - 實驗報告


0. 字節流與二進制文件

我的代碼


public class Main {
    public static void main(String[] args)
    {
        String fileName="d:\\testStream\\0\\student.data";
        try(DataOutputStream dos=new DataOutputStream(new FileOutputStream(fileName)))
        {
        	Student stu1=new Student(1,"zhang",13,80);
        	dos.writeInt(stu1.getId());
        	dos.writeUTF(stu1.getName());
        	dos.writeInt(stu1.getAge());
        	dos.writeDouble(stu1.getGrade());
        } catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        try(DataInputStream dis=new DataInputStream(new FileInputStream(fileName)))
        {
        	int id=dis.readInt();
        	String name=dis.readUTF();
        	int age=dis.readInt();
        	double grade=dis.readDouble();
        	Student stu=new Student(id,name,age,grade);
        	System.out.println(stu);
        } catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    }
}

我的總結

一、 使用DataOutputStream與FileOutputStream將Student對象寫入二進制文件student.data

  1. 二進制文件與文本文件的區別
  • 二進制文件可以存儲int/double/char..等基本數據類型,文本文件只能存儲char型變量。因此文本文件在讀取或存儲過程中常需要用到類型轉換(類似parseInt)

2.try...catch...finally注意事項

  • catch多個異常時要注意異常寫的先后順序,總體來說越大的(父類)異常要放越后面。可以直接使用eclipse的提示功能直接自己生成異常,方便又不會出錯。

3.使用try..with...resouces關閉資源

  • 是jdk8新的語法,可以直接在try(........)的括號中定義最后要關閉的資源,在運行結束后會自動關閉,不需要傳統地在finally中關閉資源。用法詳見上面代碼塊。

1. 字符流與文本文件

我的代碼

任務1

String fileName="d:\\testStream\\1\\Students.txt";
List<Student> studentList = new ArrayList<>();
		try(
			FileInputStream fis=new FileInputStream(fileName);
			InputStreamReader isr=new InputStreamReader(fis, "UTF-8");
			BufferedReader br=new BufferedReader(isr))
		{
			String line=null;
			while((line=br.readLine())!=null)
			{
				String[] msg=line.split("\\s+");
				int id=Integer.parseInt(msg[0]);
				String name=msg[1];
				int age=Integer.parseInt(msg[2]);
				double grade=Double.parseDouble(msg[3]);
				Student stu=new Student(id,name,age,grade);
				studentList.add(stu);
			}
		} 
		catch (FileNotFoundException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
		catch (IOException e) 
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(studentList);

任務2

public static List<Student> readStudents(String fileName)
	{
		List<Student> studentList = new ArrayList<>();
		try(
			FileInputStream fis=new FileInputStream(fileName);
			InputStreamReader isr=new InputStreamReader(fis, "UTF-8");
			BufferedReader br=new BufferedReader(isr))
		{
			String line=null;
			while((line=br.readLine())!=null)
			{
				String[] msg=line.split("\\s+");
				int id=Integer.parseInt(msg[0]);
				String name=msg[1];
				int age=Integer.parseInt(msg[2]);
				double grade=Double.parseDouble(msg[3]);
				Student stu=new Student(id,name,age,grade);
				studentList.add(stu);
			}
		} 
		catch (FileNotFoundException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
		catch (IOException e) 
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return studentList;
	}

任務3

String fileName="d:\\testStream\\1\\Students.txt";
try(
			FileOutputStream fos=new FileOutputStream(fileName,true);
			OutputStreamWriter osw=new OutputStreamWriter(fos,"UTF-8");
			PrintWriter pw=new PrintWriter(osw))
		{
			pw.println();
			pw.print("4 一一 13 80");
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

任務4

String fileName1="d:\\testStream\\1\\Students.dat";
try(
			FileOutputStream fos=new FileOutputStream(fileName1);
			ObjectOutputStream oos=new ObjectOutputStream(fos))
		{
			Student ts=new Student(5,"asd",14,60);
			oos.writeObject(ts);
		}
		catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try(
			FileInputStream fis=new FileInputStream(fileName1);
			ObjectInputStream ois=new ObjectInputStream(fis))
		{
			Student newStudent =(Student)ois.readObject();
			System.out.println(newStudent);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

我的總結

  • 在任務1、2、3中,程序生成的txt文件是指定的UTF-8編碼。后續如果人為地通過系統自帶的文本文檔打開Students.txt並進行保存,該文本會變成UTF-8-BOM編碼。這樣程序再次運行時就會報錯,因為指定的UTF-8跟文件實際上的UTF-8-BOM是不一樣的,這個問題困擾了我一段時間,目前我的解決方法是兩個:不人為保存,或者需要人為保存時用notepad++。
  • 任務3中一開始PrintWriter會直接覆蓋原文件,通過查閱資料,在構造FileOutputStream時多傳一個true就可以了。
  • 任務4中,一開始是讓對象流寫在txt中,后面發現會發生亂碼。通過查閱資料知道writeObject()的作用是讓實例以文件的形式保存在磁盤上,而這個文件是用二進制的形式寫的,所以就讓對象流的處理文件是bat格式,就沒錯了。

2.緩沖流

我的代碼


public class Main2 {
	public static void main(String[] args) {
		String fileName="d:\\testStream\\2\\test.txt";
		try (PrintWriter pw = new PrintWriter(fileName);)
		{
			Random random=new Random();
			random.setSeed(100);
			double sum=0,aver;
		    for (int i = 0; i < 1000_0000; i++) {
		    	int r=random.nextInt(10);
		    	sum+=r;
		        pw.println(r);
		    }
		    aver=sum/1000_0000;
		    System.out.format("%.5f", aver);
		    
		} catch (FileNotFoundException e) {
		    e.printStackTrace();
		}
	}
}

JUNIT測試部分


import static org.junit.jupiter.api.Assertions.*;

import java.io.*;
import java.util.*;
import org.junit.jupiter.api.Test;

class testBufferedReader {
	String fileName="d:\\testStream\\2\\test.txt";
	@Test
	void testScanner() {
		try (	FileInputStream fis = new FileInputStream(fileName);
				Scanner sc=new Scanner(fis))
		{
			while(sc.hasNextInt())
			{
				sc.nextInt();
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}finally
		{
			System.out.println("sc end");
		}
	}
	@Test
	void testBufferedReader() {
		try (	FileReader fr = new FileReader(fileName);
				BufferedReader br=new BufferedReader(fr))
		{
			String line=null;
			while((line=br.readLine())!=null)
			{
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}finally
		{
			System.out.println("br end");
		}
	}
}

我的總結

  • 生成隨機數平時用的少,每次需要用時都得先找點資料,要盡量記住常見的用法。
  • 在將隨機數寫入文件時,如果用的是print而不是println,文本大小會是println的三分一(1000_0000字節和3000_0000字節),因為一個回車2字節,沒有寫回車的話junit跑出來的結果Scanner和BufferedReader的時間是差不多的,而寫了回車時間差距就很大。
  • JUNIT中要測試的方法前要加上@Test

3.字節流之對象流

我的代碼

public static void writeStudent(List<Student> stuList)
	{
		String fileName="d:\\testStream\\3\\Students.dat";
		try (	FileOutputStream fos=new FileOutputStream(fileName);
				ObjectOutputStream ois=new ObjectOutputStream(fos))
		{
			ois.writeObject(stuList);
			
		} 
		catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
	}
public static List<Student> readStudents(String fileName)
	{
		List<Student> stuList=new ArrayList<>();
		try (	FileInputStream fis=new FileInputStream(fileName);
				ObjectInputStream ois=new ObjectInputStream(fis))
		{
			stuList=(List<Student>)ois.readObject();
		} 
		catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return stuList;
	}	

我的總結

  • 使用對象流時,寫入的是一個對象,而不是多個對象。在這里不用像用BufferedReader時一行一個Student對象地讀取,而是直接讀出一個集合或數組

5.文件操作

我的代碼

遞歸


public class Main5 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Path dir=Paths.get("D:\\", "testStream","5");
		findFile(dir,"c.txt");
	}
	public static void findFile(Path dir,String fileName)
	{
		File file=dir.toFile();
		File[] files=file.listFiles();
		for(File now:files)
		{
			if(now.isFile())
			{
				if(now.getName().equals(fileName))
				{
					System.out.println(now.getAbsolutePath());
					return;
				}
			}
			else if(now.isDirectory())
			{
				findFile(now.toPath(),fileName);
			}
		}
	}
}

隊列


我的總結

  • File類和Path類可以互相轉換,Path是File的升級。
  • Paths類可以直接獲得Path對象,不需要new Path。

6.正則表達式

我的代碼

任務1


public class Main6 {

	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		Pattern pattern=Pattern.compile("^[+-]?[0-9]+(\\.\\d+)?");
		Matcher matcher=null;
		while(sc.hasNext())
		{
			String str=sc.next();
			matcher=pattern.matcher(str);
			System.out.println(matcher.matches());
		}
		sc.close();
	}
}

任務2-匹配數字字符串

package javalearning;

import java.io.*;
import java.net.*;
import java.util.regex.*;

/**
 * This program displays all URLs in a web page by matching a regular expression that describes the
 * <a href=...> HTML tag. Start the program as <br>
 * java HrefMatch URL
 * @version 1.01 2004-06-04
 * @author Cay Horstmann
 */
public class HrefMatch
{
   public static void main(String[] args)
   {
      try
      {
         // get URL string from command line or use default
        /* String urlString;
         if (args.length > 0) urlString = args[0];
         else urlString = "http://java.sun.com";*/
    	 String fileName="D:\\testStream\\6\\集美大學-計算機工程學院.htm";
         // open reader for URL
        //InputStreamReader in = new InputStreamReader(new URL(urlString).openStream());
    	 InputStreamReader in = new InputStreamReader(new FileInputStream(fileName));
         // read contents into string builder
         StringBuilder input = new StringBuilder();
         int ch;
         while ((ch = in.read()) != -1)
            input.append((char) ch);

         String patternString = "[+-]?[0-9]+(\\.\\d+)?";
         Pattern pattern = Pattern.compile(patternString, Pattern.CASE_INSENSITIVE);
         Matcher matcher = pattern.matcher(input);

         while (matcher.find())
         {
            int start = matcher.start();
            int end = matcher.end();
            String match = input.substring(start, end);
            System.out.println(match);
         }
      }
      catch (IOException e)
      {
         e.printStackTrace();
      }
      catch (PatternSyntaxException e)
      {
         e.printStackTrace();
      }
   }
}

任務2-匹配圖片字符串(僅展示部分,其余同數字字符串匹配)

         String patternImgString = "img\\s[a-zA-Z]+=\".*.(gif|png|jpg|jpeg)\"";
         Pattern pattern = Pattern.compile(patternImgString, Pattern.CASE_INSENSITIVE);
         Matcher matcher = pattern.matcher(input);

我的總結

  • 要熟練匹配字符串平時就要多寫正則表達式,匹配圖片字符串的patternImgString寫了一段時間,最后還是沒有做到完美的匹配(特殊情況會匹配不准確)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM