Core Java 8 读书笔记

编程入门 行业动态 更新时间:2024-10-10 09:19:34

Core Java 8 <a href=https://www.elefans.com/category/jswz/34/1768764.html style=读书笔记"/>

Core Java 8 读书笔记

Core Java 8 读书笔记-流和文件

作者:老九—技术大黍

原文:Core Java 8th Edition

社交:知乎

公众号:老九学堂(新人有惊喜)

特别声明:原创不易,未经授权不得转载或抄袭,如需转载可联系笔者授权

前言

当我们读完了《Thinking in Java》之后,要进精进地学Java编程语言,那么一定要看《Core Java》一书。下面是我的读书笔记。

在Java API中,我们可以以字节序列读取的对象叫一个输入流(In the Java API, an object from which we can a sequence of bytes is called an input stream)。一个可以被字节序列被写的对象叫做输出流。而这些被操作的序列字节资源和目标常常是文件,也可能是网络连接和内存块。InputStream和OutputStream是抽象类,它们是I/O类的老祖宗。

因为字节流不能直接处理Unicode码存贮的信息,所以API单独把处理Unicode字符的类独立出来Reader和Writer两个抽象类。这两个灰是基于两个字节处理的,而不是一个字节处理的I/O流。

读取和写入字节

InputStream类一个抽象方法

abstract int read();
复制代码

该方法一个字节一个字节的读取,然后一个字节一个字节的返回读取的内容,如果读完输入资源,那么返回-1。实现类必须重写该方法,以完成自己特定的功能。比如,FileInputStream类它从一个方法读字节。System.in是InputStream类的预定字类对象,它允许你从键盘读取信息。

InputStream类也有非抽象方法用来读取字节或者跳过字节的动作。这些访问会呼叫abstract read方法,所以子类只需要重写一个抽象方法即可。

不管是read和write方法它们在实际读取或者写入动作时,都会锁定(block)资源。这就意味着流对象不能立即被访问(一般为网络连接忙碌),或者当前线程锁定,结果会使其它线程等待流对象,并且该对象可用。available方法可以让我们检查当前读取字节数

int bytesAvailabe = in.available();
if(bytesAvailabe > 0){byte[] data = new byte[bytesAvailabe];in.read(data);
}
复制代码

当我们读完流对象之后,需要呼叫close方法关闭流。

字节流对象

Java把流分为字节流和字符流。FileInputStream可以通过openStream方法从URL类得到流对象。PrintWriter和DataInputStream类可以把字符组合成有用的数据类型。Java程序可以整合使用这些流来操作文件。

ShowStreams类

package com.jb.arklis.demo;
import com.jb.arklis.zip.*;
import static java.lang.System.*;
import java.io.*;
import java.util.zip.*;
import java.util.*;
import com.jb.arklis.text.*;
import java.nio.charset.*;
import com.jb.arklis.random.*;
import com.jb.arklis.ser.*;
import com.jb.arklis.reg.*;/**功能:书写一个类用来演示流和文件的使用作者:技术大黍备注:java.io包中的相对用户的工作目录(user's working directory),如果想知道当前的工作目录,那么呼叫System.getProperty("user.dir");*/
public class ShowStreams{public ShowStreams(){out.println(System.getProperty("user.dir"));//demoStreamFilter();//demoPushbackInputStream();//demoReadZipFile();//demoCharsetdemoPrintWriter();//测试操作文本文档//new TextFileOperationShow();//demoCharset();//demoRandomFileAccess();//演示压缩流对象的使用//new ZipFileFrame();//new ObjectStreamTest();//new RegExTest();new HrefMatch();}//不管怎样修改文件内容都一个固定的双精度数值private void demoStreamFilter(){try{FileInputStream fileInput = new FileInputStream("employee.dat");//然后读入到内容DataInputStream dataInput = new DataInputStream(fileInput);//最后读成Java的数据内容double salary = dataInput.readDouble();out.println("当前薪水是:" + salary);}catch(Exception e){out.print(e.getMessage());}}private void demoPushbackInputStream(){try{PushbackInputStream pushInput = new PushbackInputStream(new BufferedInputStream(new FileInputStream("employee.dat")));int b = pushInput.read();if(b != '<'){pushInput.unread(b);out.println("当前b是:" + b);}}catch(Exception e){out.print(e.getMessage());}}private void demoReadZipFile(){try{ZipInputStream zipInput = new ZipInputStream(new FileInputStream("employee.rar"));DataInputStream dataInput = new DataInputStream(zipInput);out.println("当前压缩档大小是:" + dataInput.readChar());}catch(Exception e){out.print(e.getMessage());}}private void demoPrintWriter(){try{PrintWriter outInput = new PrintWriter("employee.dat","GBK");String name = "Arklis 曾";double salary = 75000.0;outInput.print(name + ' ' + salary);outInput.flush();outInput.close();}catch(Exception e){out.println(e.getMessage());}}//字符集是大小写敏感的private void demoCharset(){Charset charset = Charset.forName("ISO-8859-1");//得到该字符集的别名Set<String> aliases = charset.aliases();for(String x : aliases){out.println(x);}}private void demoRandomFileAccess(){new RandomwFileTest();}public static void main(String[] args){new ShowStreams();}
}

文本的输入与输出

当我们保存数据时,必须选择是使用二进制方式还是使用文本格式来保存。比如如果把整数1234保存为二进制形式,那么它的二进制字节序列是00 00 04 D2(16进制形式)。如果使用文本格式,那么它就是字符串“1234”格式。虽然二进制的I/O流的速度快,但是它的可读性不好。

当我们保存为文本字符串时,那么我们需要考虑字符编码问题(character encoding)。在UTF-16编码,字符串”1234”的编码是00 31 00 32 00 33 00 34(16进制方式),大多数程序都有不同的编码要求。ISO 8859-1编码是美国与西欧使用的试,这些“1234”会被编码为31 32 33 34没有0字节。

OutputStreamWriter类会把unicode字符转转换成字节流,转换时使用指定的编码方式对字符串进行编码。相对于InputSreamReader类会把不同的、指定的编码字符转换成unicode码字符。比如,我们使用如下命令:

InputStreamReader in = new InputStreamReader(System.in);

该命令是把控制输入的内容转换为unicode码字符。而下面命令是:

InputStreamReader in = new InputStreamReader(new FileInputStream(“kremli.dat”),”iso8859-1”);

它把.kremli.dat文档转换成iso8859-1编码格式的字符串。

TextFileOperationShow类

package com.jb.arklis.text;
import java.util.*;
import static java.lang.System.*;
import java.io.*;
import com.jb.arklis.random.*;
/*测试的模式类*/
public class Employee implements Serializable{public static final int NAME_SIZE = 40;public static final int RECORD_SIZE = 2 * NAME_SIZE + 8 + 4 + 4 + 4;private String name;private double salary;private Date hireDay;public Employee(){}public Employee(String name, double salary, int year, int month, int day){this.name = name;this.salary = salary;GregorianCalendar calendar = new GregorianCalendar(year,month -1, day);hireDay = calendar.getTime();		}/**加薪*/public void raiseSalary(double byPercent){double raise = salary * byPercent / 100;salary += raise;}public String toString(){return getClass().getName() + "[name=" + name + ",salary="+ salary + ",hireDay=" + hireDay + "]";}//员工执行输出持久化动作--把每个员的信息持久化文本文档中去public void writeData(PrintWriter output){GregorianCalendar calendar = new GregorianCalendar();calendar.setTime(hireDay);output.println(name + "|" + salary + "|" + calendar.get(Calendar.YEAR)+ "|" + (calendar.get(Calendar.MONTH) + 1) + "|" +calendar.get(Calendar.DAY_OF_MONTH));}//重载writeData方法public void writeData(DataOutput output){try{//处理字符串比较特殊一些DataIO.writeFixedString(name,NAME_SIZE, output);//执行持久化输出动作output.writeDouble(salary);GregorianCalendar calendar = new GregorianCalendar();calendar.setTime(hireDay);//输出日期output.writeInt(calendar.get(Calendar.YEAR));output.writeInt(calendar.get(Calendar.MONTH) + 1);output.writeInt(calendar.get(Calendar.DAY_OF_MONTH));}catch(Exception e){e.printStackTrace();}}/**从持久化文本文件中读取每个员工的信息*/public void readData(Scanner input){String line = input.nextLine(); //读取每一行字符串//out.println("当前持久文档中的第一行数据是:" + line);String[] tokens = line.split("\\|"); //把|排出name = tokens[0];salary = Double.parseDouble(tokens[1]);int year = Integer.parseInt(tokens[2]);int month = Integer.parseInt(tokens[3]);int day = Integer.parseInt(tokens[4]);GregorianCalendar calendar = new GregorianCalendar(year,month - 1,day);hireDay = calendar.getTime();}//重载readData()方法public void readData(DataInput input)throws IOException{//读取字符串比较特殊name = DataIO.readFixedString(NAME_SIZE, input);salary = input.readDouble();//读取日期int y = input.readInt();int m = input.readInt();int d = input.readInt();GregorianCalendar calendar = new GregorianCalendar(y,m-1,d);hireDay = calendar.getTime();}public String getName() {return name;}public void setName(String name) {this.name = name;}public double getSalary() {return salary;}public void setSalary(double salary) {this.salary = salary;}public Date getHireDay() {return hireDay;}public void setHireDay(Date hireDay) {this.hireDay = hireDay;}}

Employee类

package com.jb.arklis.text;
import java.util.*;
import static java.lang.System.*;
import java.io.*;
import com.jb.arklis.random.*;
/*测试的模式类*/
public class Employee implements Serializable{public static final int NAME_SIZE = 40;public static final int RECORD_SIZE = 2 * NAME_SIZE + 8 + 4 + 4 + 4;private String name;private double salary;private Date hireDay;public Employee(){}public Employee(String name, double salary, int year, int month, int day){this.name = name;this.salary = salary;GregorianCalendar calendar = new GregorianCalendar(year,month -1, day);hireDay = calendar.getTime();		}/**加薪*/public void raiseSalary(double byPercent){double raise = salary * byPercent / 100;salary += raise;}public String toString(){return getClass().getName() + "[name=" + name + ",salary="+ salary + ",hireDay=" + hireDay + "]";}//员工执行输出持久化动作--把每个员的信息持久化文本文档中去public void writeData(PrintWriter output){GregorianCalendar calendar = new GregorianCalendar();calendar.setTime(hireDay);output.println(name + "|" + salary + "|" + calendar.get(Calendar.YEAR)+ "|" + (calendar.get(Calendar.MONTH) + 1) + "|" +calendar.get(Calendar.DAY_OF_MONTH));}//重载writeData方法public void writeData(DataOutput output){try{//处理字符串比较特殊一些DataIO.writeFixedString(name,NAME_SIZE, output);//执行持久化输出动作output.writeDouble(salary);GregorianCalendar calendar = new GregorianCalendar();calendar.setTime(hireDay);//输出日期output.writeInt(calendar.get(Calendar.YEAR));output.writeInt(calendar.get(Calendar.MONTH) + 1);output.writeInt(calendar.get(Calendar.DAY_OF_MONTH));}catch(Exception e){e.printStackTrace();}}/**从持久化文本文件中读取每个员工的信息*/public void readData(Scanner input){String line = input.nextLine(); //读取每一行字符串//out.println("当前持久文档中的第一行数据是:" + line);String[] tokens = line.split("\\|"); //把|排出name = tokens[0];salary = Double.parseDouble(tokens[1]);int year = Integer.parseInt(tokens[2]);int month = Integer.parseInt(tokens[3]);int day = Integer.parseInt(tokens[4]);GregorianCalendar calendar = new GregorianCalendar(year,month - 1,day);hireDay = calendar.getTime();}//重载readData()方法public void readData(DataInput input)throws IOException{//读取字符串比较特殊name = DataIO.readFixedString(NAME_SIZE, input);salary = input.readDouble();//读取日期int y = input.readInt();int m = input.readInt();int d = input.readInt();GregorianCalendar calendar = new GregorianCalendar(y,m-1,d);hireDay = calendar.getTime();}public String getName() {return name;}public void setName(String name) {this.name = name;}public double getSalary() {return salary;}public void setSalary(double salary) {this.salary = salary;}public Date getHireDay() {return hireDay;}public void setHireDay(Date hireDay) {this.hireDay = hireDay;}}

写数据为二进制时使用DataOutputStream类;如果想写成文本格式时使用PrintWriter类来实现。那么,当我们需要读入数据到内存中,我们使用使用DataInputStream类来读二进制数据,在J2SE 5.0以后使用Scanner类来读文本字符,但是在J2SE 5.0以前都使用BufferedReader类来读取文本字符。

读取和写入二进制数据

DataOutput接口定义了写入数字、字符和boolean值为二进制格式的方法:

  • writeChars
  • writeByte
  • writeInt
  • writeShort
  • writeLong
  • writeFloat
  • writeDouble
  • writeChar
  • writeBoolean
  • writeUTF

比如writeInt方法总是会把一个整数写成四个字节的二进制数字,而不管数的进制;writeDouble总是会把双精度数写成八个字节的二进制数字。它们的输出没有阅读性,但是每个数据类型的所使用的空间是一样大小的,所以它们解析成文本时的速度很快。其中writeUTF方法把字符数据转换成八位的unicode编码格式。

RandomAccessFile类可以让我们在一个文件中随机查找或者写入数据。注意:该磁盘文件是可以随机访问的,但是来自网络流数据是不可以随机访问的。如果使用该类,那么可以实现对二者的只读和读/写操作,方式是通过在构造方法中使用“r”和”rw”字符串指定即可。

DataIO类

package com.jb.arklis.random;
import static java.lang.System.*;
import java.io.*;/**书写一个工具类,用来实现二进制字符集的读写操作作者:技术大黍*/
public class DataIO{public static String readFixedString(int size, DataInput input)throws IOException{StringBuilder message = new StringBuilder(size);int i = 0;boolean more = true;while(more && i < size){char ch = input.readChar();i++;if(ch == 0){//如果字符是结束符more = false;//那么不读}else{//否则所字符添加到字符串中去message.append(ch);}}input.skipBytes(2 * (size - i)); //该语句是关键语句,该方法不抛出 EOFException异常return message.toString();}//对比Employee类的writeData方法看看有何不同--一个是字符串,一个字符方式。public static void writeFixedString(String temp, int size, DataOutput output)throws IOException{for(int i = 0 ; i < size; i++){char ch = 0;//进行字符串的写动作if(i < temp.length()){//那么取出字符串的每个字符ch = temp.charAt(i);}//输出字符output.writeChar(ch);}}
}

RandomwFileTest类

package com.jb.arklis.random;
import static java.lang.System.*;
import com.jb.arklis.text.*;
import java.io.*;
import java.nio.charset.*;
/**功能:书写一个随机访问文件类,用来演示通过字节集来进行读取和写入文件的动作作者:技术大黍备注:我们使用二进制流处理字符集的方式实现文件的读取与写入动作。*/
public class RandomwFileTest{private Employee[] staff = new Employee[5];public RandomwFileTest(){staff[0] = new Employee("Carl Cracker", 75000, 1987, 12,15);staff[1] = new Employee("Arklis Zeng", 75000, 1989, 10,1);staff[2] = new Employee("Harray Hacker", 50000, 1990, 3,15);staff[3] = new Employee("Tony Tester", 40000, 1991, 4,22);staff[4] = new Employee("Huward Beast", 100000, 1988, 9,21);try{//指定输出的文件路径DataOutputStream output = new DataOutputStream(new FileOutputStream("./src/com/jb/arklis/random/employee.dat"));for(Employee e: staff){e.writeData(output);}output.close();out.println("输出完毕!");//下面获取数据,然后初始化对象数组RandomAccessFile input = new RandomAccessFile("./src/com/jb/arklis/random/employee.dat","r");//计算数据的大小int n = (int)(input.length() / Employee.RECORD_SIZE);Employee[] newStaff = new Employee[n];//读取for(int i = n - 1; i >= 0; i--){newStaff[i] = new Employee();//读取当前文件中每一行内容input.seek(i * Employee.RECORD_SIZE);newStaff[i].readData(input);}input.close();//打印出来for(Employee e: newStaff){out.println(e);}}catch(Exception e){e.printStackTrace();}}
}

压缩文件

ZIP压缩文档可以保存一个或者多个压缩格式的文件,每个ZIP文档都有一个头信息供压缩方法使用。我们可以通过使用ZipInputStream类读取通过ZipOutputStream类写成的压缩档。

ZipFileFrame类

package com.jb.arklis.zip;
import static java.lang.System.*;
import java.io.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.zip.*;
import java.util.*;/**功能:书写一个窗体类,用来演示怎样压缩文档作者:技术大黍		*/
public class ZipFileFrame extends JFrame{private JComboBox fileCombo;private JTextArea fileText;private String zipName;public ZipFileFrame(){setTitle("压缩流对象的操作演示");Container container = getContentPane();init(container);setSize(400,300);setDefaultCloseOperation(EXIT_ON_CLOSE);setLocationRelativeTo(null);setVisible(true);zipFile();}private void zipFile(){try{FileOutputStream fout = new FileOutputStream("test.zip");ZipOutputStream zout = new ZipOutputStream(fout);ZipEntry ze = new ZipEntry("./src/com/jb/arklis/demo/ShowStreams.java");zout.putNextEntry(ze);zout.closeEntry();ze = new ZipEntry("./src/com/jb/arklis/random/RandomwFileTest.java");zout.putNextEntry(ze);zout.closeEntry();zout.close();}catch(Exception e){e.printStackTrace();}}private void init(Container container){//添加菜单对象JMenuBar menuBar = new JMenuBar();JMenu menu = new JMenu("文件");JMenuItem openItem = new JMenuItem("打开");menu.add(openItem); //添加打开菜单项//处理打开文件事件openItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent event){//创建一个文件选择器对象,用来指定需要压缩的对象JFileChooser chooser = new JFileChooser();chooser.setCurrentDirectory(new File("."));//指定当前工作目录//打开当前文档所在路径int read = chooser.showOpenDialog(ZipFileFrame.this);//如果可以添加到对话框if(read == JFileChooser.APPROVE_OPTION){//那么取得当前选中文件的路径zipName = chooser.getSelectedFile().getPath();fileCombo.removeAllItems();//扫描压缩文档scanZipFile();}}});JMenuItem exitItem = new JMenuItem("退出");menu.add(exitItem);exitItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent event){exit(0);}});menuBar.add(menu);setJMenuBar(menuBar); //添加菜单条//添加文本域和combo boxfileText = new JTextArea();fileCombo = new JComboBox();fileCombo.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent event){//装载zip文件loadZipFile((String)fileCombo.getSelectedItem());}});container.add(fileCombo,BorderLayout.SOUTH);container.add(new JScrollPane(fileText),BorderLayout.CENTER);}private void loadZipFile(final String name){fileCombo.setEnabled(false);fileText.setText("");new SwingWorker<Void, Void>(){protected Void doInBackground()throws Exception{try{//读取压缩文件ZipInputStream zipInput = new ZipInputStream(new FileInputStream(zipName));ZipEntry entry = zipInput.getNextEntry();//找到匹配的压缩档while(entry!= null){if(entry.getName().equals(name)){//那么读到内存中//Scanner scanner = new Scanner(new FileReader(zipName));String entryName = entry.getName();File newFile = new File(entryName);String directory = newFile.getParent();//判断是否是一个文件if(directory == null){if(newFile.isDirectory()){break;}}//readByRandomAccessFile(entryName);//使用RandomAccessFile类读,中文有乱码问题//readByFileReader(entryName); //正确显示不会有乱码问题readByScanner(entryName); //使用scanner来读文件}zipInput.closeEntry(); //读下一压缩项entry = zipInput.getNextEntry();}zipInput.close();}catch(Exception e){e.printStackTrace();}return null;}private void readByScanner(String entryName)throws IOException{Scanner scanner = new Scanner(new FileReader(entryName));while(scanner.hasNextLine()){fileText.append(scanner.nextLine());fileText.append("\n");}}//使用BufferedReader不用担心文件的长度问题与文件指针移动问题private void readByFileReader(String entryName)throws IOException{FileReader fileReader = new FileReader(entryName);BufferedReader bufferedReader = new BufferedReader(fileReader);String line = bufferedReader.readLine();while(line != null){fileText.append(line);fileText.append("\n");line = bufferedReader.readLine();}fileReader.close();}private void readByRandomAccessFile(String entryName)throws IOException{RandomAccessFile randomFile = new RandomAccessFile(entryName,"r");String line;while((line = randomFile.readLine()) != null){fileText.append(line);fileText.append("\n");}randomFile.close();}//重写done()方法protected void done(){fileCombo.setEnabled(true);}}.execute();}/**扫描压缩档内容,并且生产combo box对象*/private void scanZipFile(){new SwingWorker<Void, String>(){protected Void doInBackground()throws Exception{ZipInputStream zipInput = new ZipInputStream(new FileInputStream(zipName));//声明一个压缩项ZipEntry entry;while((entry = zipInput.getNextEntry()) != null){//如果有数据项//那么把资源发送到当前线程来处理publish(entry.getName());zipInput.closeEntry();}zipInput.close();return null;}//重写process方法,用来处理压缩项protected void process(java.util.List<String> names){for(String x : names){fileCombo.addItem(x); //combo组件添加项}}}.execute();}
}

运行效果

对象流和序列化

这张图表述了两个经理共用一个秘书。

内存与文件存贮的比较。

Manager类

package com.jb.arklis.ser;
import static java.lang.System.*;
import com.jb.arklis.text.*;public class Manager extends Employee{private Employee secretary;public void setSecretary(Employee secretary){this.secretary = secretary;}public Employee getSecretary(){return secretary;}public Manager(){}public String toString(){return super.toString() + "[secretary=" + secretary + "]";}public Manager(String name, double salary, int year, int month, int day){super(name,salary,year,month,day);secretary = null;}
}

ObjectStreamTest类

package com.jb.arklis.ser;
import static java.lang.System.*;
import java.io.*;
import com.jb.arklis.text.*;/**功能:书写一个演示对象流的类作者:技术大黍*/
public class ObjectStreamTest{private Employee[] staff = new Employee[3];public ObjectStreamTest(){Employee harry = new Employee("Harray Hacker", 50000, 1990, 3,15);Manager arklis = new Manager("Arklis Zeng", 75000, 1989, 10,1);arklis.setSecretary(harry);Manager tony = new Manager("Tony Tester", 70000, 1991, 4,22);tony.setSecretary(harry);staff[0] = harry;staff[1] = arklis;staff[2] = tony;//对数组执行序列化和反序列化try{ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream("./src/com/jb/arklis/ser/employee.dat"));output.writeObject(staff);output.close();//读取对象ObjectInputStream input = new ObjectInputStream(new FileInputStream("./src/com/jb/arklis/ser/employee.dat"));Employee[] newStaff = (Employee[])input.readObject();input.close();//给第二个员工加薪10%newStaff[1].raiseSalary(10);//显示出来for(Employee e: newStaff){out.println(e);}}catch(Exception e){e.printStackTrace();}}
}

NIO

NIO包的导入是为了解决原IO包读/写速度的问题:

演示代码

package com.jb.arklis.io.nio;
import static java.lang.System.*;
import java.nio.*;
import java.nio.channels.*;
import java.io.*;/**功能:书写一个类用来演示文件锁的使用作者:技术大黍备注:注意这里使用内存影射文件与文件锁的功能*/
public class LockingMappedFiles{static final int LENGTH = 0x4FFFF; //128MB 0x8FFFFFFstatic FileChannel channel;public static void showFileLock()throws IOException{channel = new RandomAccessFile("testfilelock.dat","rw").getChannel();//内存影射文件MappedByteBuffer output = channel.map(FileChannel.MapMode.READ_WRITE, 0, LENGTH);//使用内存影射文件对通道进行写操作for(int i = 0; i < LENGTH; i++){output.put((byte)'x');}//对通道进行锁定new LockAndModify(output, 0, 0 + LENGTH / 3);new LockAndModify(output, LENGTH / 2, LENGTH / 2 + LENGTH / 4);}//定义一个私有表态类,用来处理锁定义文件的动作private static class LockAndModify extends Thread{private ByteBuffer buffer;private int start, end;//在构造方法初始化成员变量LockAndModify(ByteBuffer buffer, int start, int end){this.start = start;this.end = end;buffer.limit(end);//指定缓存上限buffer.position(start);//指定缓存起始位置this.buffer = buffer.slice();start(); //起动线程}//重写run()方法public void run(){try{//执行锁定动作FileLock lock = channel.lock(start, end, false);//显示锁定结果out.println("Locked:(锁定) " + start + " to(到) " + end);//执行修改动作while(buffer.position() < buffer.limit() - 1){buffer.put((byte)(buffer.get() + 1));}//释放锁lock.release();out.println("Released:(释放) " + start + " to(到) " + end);}catch(Exception e){out.println(e.getMessage());}}}
}/**功能:书写一个显示可用字节码来显示字符的类作者:技术大黍*/
public class GetDataFromByteBuffer{private static final int BUFFER_SIZE = 1024;public static void showCharFromByte(String test)throws IOException{ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);//允许缓存自动增长int i = 0;while(i++ < buffer.limit()){if(buffer.get() != 0){print("不是零");}}//否则打印i值print("i = " + i);buffer.rewind(); //输出//然后存贮字符,接着显示它们buffer.asCharBuffer().put(test);char c;while((c = buffer.getChar()) != 0){printnb(c + " "); //把字符显示出来}print();buffer.rewind();//在缓存中存整数,然后显示出来buffer.asShortBuffer().put((short)471143);print(buffer.getShort());buffer.rewind();buffer.asIntBuffer().put(99471143);print(buffer.getInt());buffer.rewind();buffer.asFloatBuffer().put(99471143);print(buffer.getFloat());buffer.rewind();}
}/**功能:书写一个nio类,用来学nio包的使用作者:技术大黍*/
public class GetChannel{//定义一个数据传送单位private static final int BYTE_SIZE = 1024;public static void useChannel(String filename){try{//使用channel来生成一个文件FileChannel channel = new FileOutputStream(filename).getChannel();//使用channel把向缓存中写内容channel.write(ByteBuffer.wrap("测试数据字符(Test Data)\n".getBytes()));channel.close();//经今夜的添加一些内容channel = new RandomAccessFile(filename,"rw").getChannel();//把文件指针移动到尾部channel.position(channel.size());//写一些数据channel.write(ByteBuffer.wrap("添加一些测试数据而已(Add some test data)。。。".getBytes()));//关闭通道对象channel.close();//演示出来channel = new FileInputStream(filename).getChannel();//使用缓存来装载ByteBuffer buffer = ByteBuffer.allocate(BYTE_SIZE);//读取通道中去channel.read(buffer);//拉出数据buffer.flip();//如果缓存有while(buffer.hasRemaining()){//那么从里面合出来out.print((char)buffer.get());}}catch(Exception e){out.println(e.getMessage());}}
}/**功能:书写一个nio类,用来实现文件的拷贝功能作者:技术大黍*/
public class ChannelCopy{//定义每次使用字节的单元private static final int BUFFER_SIZE = 1024;public static void copy(String source, String target)throws IOException{//定义一个两个文件通道对象,用来完成拷贝的动作FileChannel input = new FileInputStream(source).getChannel();FileChannel output = new FileOutputStream(target).getChannel();//声明一个ByteBuffer对象,用来具体执行拷贝的功能ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);//搬东西--实现从源文件(source)拷贝到目标文件target中去while(input.read(buffer) != -1){buffer.flip(); //准备写入的动作output.write(buffer);buffer.clear(); //准备读取的动作}//以上循环可以使用下面语句代替//input.transferTo(0,input.size(),output); //输入对象使用TO//output.transferFrom(input, 0, input.size());//输出对象使用FromJOptionPane.showMessageDialog(null,"文件拷贝完毕!");}
}/**功能:书写一个显示可用字符集的类作者:技术大黍*/
public class AvailableCharSets{public void showCharSets(){//使用Map来列字可用字符集SortedMap<String,Charset> charSets = Charset.availableCharsets();//使用迭代器取出现键Iterator<String> iterator = charSets.keySet().iterator();//循环显示集合中的内容while(iterator.hasNext()){String charSetName = iterator.next();//打印出来printnb(charSetName);Iterator aliases = charSets.get(charSetName).aliases().iterator();//如果有键if(aliases.hasNext()){printnb(": "); //打印冒号}//然后显示出值while(aliases.hasNext()){printnb(aliases.next());//如果有多个值if(aliases.hasNext()){printnb(", ");//打印逗号}}print();//换行}} 
}

补充:Java正则表达式

正则表达式用来指定特定的字符串格式。比如

​ [Jj]ava.+

它表示匹配的字符串如下:

  1. 开头字母是J或者j
  2. 紧接着右边是三个字母ava
  3. 在ava右边是至少一个任意的字符

那么,”javaness”满足以上表达式,而”Core java”不满足以上表达式。下面我们来讲解正则表达式的语法:

1、大多数字符匹配自己,比如前面的ava 2、’.’符号表示匹配任意字符(除了一行的结束符) 3、使用’\’表示除外符,比如’.’表示一个点(.)而不是匹配任意字符,’\’表示匹配一个backslash 4、^和$分别表示一行字符的开始与结束处 5、如果X和Y是正则表达式,那么’XY’表示任意匹配X之后紧跟匹配Y,而’X|Y’表示任何匹配X的字符或者匹配Y的字符 6、可以使用数量来说明表达式,比如X+, X*或者X? 7、默认情况下,数字修饰符会以最大可能性去重复匹配,直到匹配成功。当使用后缀’?’修改表达式时,会以最少重复的方式来重复匹配;而使用‘+’时与之相反效果。比如,表达式[a-z]ab和[a-z]+ab之间的区别,前都[a-z]只匹配所有字符c,而ab只匹配ab字符;但是贪吃的[a-z]+表示字符集是cab,而剩下的ab不会再被匹配了。 8、使用’()’符号来进行子表达式的分组。比如([+-]?)([0-9]+),其中组号使用’\n’(比如’\1’)来指定分组的表达式。 测试: [+-]?[0-9]+|0[Xx][0-9A-Fa-f]+ 表达式表示的什么样的字符串?

在Java中,要求被匹配者必须是一个任意类对象,而该类必须实现CharSequence接口,比如String, StringBuilder, CharBuffer等。然后当我们编译正则表达式时,我们可使用六种标记来设置它。

Pattern pattern = Patternpile(patternString, Pattern.CASE_INSENSITIVE + Pattern.UNICODE_CASE);

六种标记如下:

如果正则表达式中有分组,那么Matcher对象可以获得分组的情况。组号0表示整个输入字符串内容;所以分组的实际第一个下标是1. 我们呼叫getCount方法得到所有分组数。

RegularTestUtil类

package com.jb.arklis.reg;
import static java.lang.System.*;
import java.util.regex.*;
import java.util.*;
import com.jb.arklis.io.nio.*;/**功能:书写一个测试正则表达式的工具类作者:技术大黍备注:输入的测试测试数据如下:Input: "abcabcabcdefabc"Regular expression: "abcabcabcdefabc"Match "abcabcabcdefabc" at positions 0-14Regular expression: "abc+"Match "abc" at positions 0-2Match "abc" at positions 3-5Match "abc" at positions 6-8Match "abc" at positions 12-14Regular expression: "(abc)+"Match "abcabcabc" at positions 0-8Match "abc" at positions 12-14Regular expression: "(abc){2,}"Match "abcabcabc" at positions 0-8*/
public class RegularTestUtil{private String pattern;private String content;private Scanner scanner;public RegularTestUtil(){init(); //初始化成员变量test(); //执行测试动作}private void init(){scanner = new Scanner(System.in); //从键盘接收输入out.println("输入正则表达式:");//如果没有输入pattern = scanner.nextLine();if(pattern == null || pattern.trim().length() == 0){out.println("请正则表达式和需要测试的数据^_^");//那么结束程序exit(0);}//否则执行测试}private void test(){out.println("输入测试数据:");content = scanner.nextLine();//具体执行测试Pattern testPattern = Patternpile(pattern);Matcher matcher = testPattern.matcher(content);//如果找到匹配对象while(matcher.find()){//那么打印出来 Print.print("匹配 \"" + matcher.group() +"\" 位置:" + matcher.start() + "-" + (matcher.end() - 1));}}
}

最后

记得给大黍❤️关注+点赞+收藏+评论+转发❤️

作者:老九学堂—技术大黍

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

更多推荐

Core Java 8 读书笔记

本文发布于:2024-02-27 09:10:28,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1705980.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:读书笔记   Core   Java

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!