JAVA高级语言重要概念以及重要的类之二(文件操作、字节流、字符流、转换流、缓冲流、内存流、打印流、扫描流等)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gyshun/article/details/84570417

1. 国际化程序实现

对于国际化程序,主要是能够在各个国家使用,功能基本上不会变化,变化的是语言,就是语言要国际化。
一般配置多个资源文件,资源文件用来配置语言的内容,一般配置文件都用.properties文件。
读取资源文件的信息使用java.util.ResourceBundle类,这是一个抽象类,但是这个类的内部提供一个Static方法,用来取得本对象.
根据当前语言环境取出:public static final ResourceBundle getBundle(String baseName);
设置指定语言:public static final ResourceBundle getBundle(String baseName,Locale locale);
代码如下:

public class NativeClassTest {
    public static void main(String[] args) throws Exception {
        ResourceBundle sb = ResourceBundle.getBundle("messages");
        System.out.println(sb.getString("gys"));
        String str = new String(sb.getString("info").getBytes("ISO-8859-1"),"GBK");
        System.out.println(MessageFormat.format(str,"gys",new SimpleDateFormat("yyyy-MM-dd").format(new Date())));
    }
}

对应的messages.properties中的内容如下:

gys=kljdlkjfkldjklfjdkl
info=你好啊{0},今天日期是:{1}

1.1 Locale类使用

Locale类是用来设置语言类,通过获取当前的语言环境来设置语言类,主要方法有:

  • 构造方法:public Locale(String language,String country);
  • 取得当前语言环境 :public static Locale getDefault();

2. 文件操作类的概念及使用

对于文件操作,在JAVA编程中相对较难的一部分,主要涉及以下内容:

  • 五个核心类:File、InputStream、OutputStream、Reader、 Writer;
  • 一个核心接口:Serializable;
    其中File类是操作文件的类,是对文件本身进行操作。
    如果想要使用File类,那么首先就需要通过它提供的构造方法定义一个要操作文件的类,主要方法有
    • 设置完整路径:public File(String pathName);大部分情况下使用此类操作
    • 设置父路径与子文件路径:public File(File parent,String child);这个在Android上使用较多

2.1 文件操作类

   - 创建文件:public boolean createNewFile() throws IOException;
   - 删除文件:public boolean delete();
   - 判断文件是否存在:public boolean exists();

注意:在文件分隔符,在Windows下使用"",而Linux下使用的是“/”,做为路径分隔符。
在FIle类里面提供有一个分隔符常量:public static final String separator;
如下代码:

public class FileTestClass {
    public static void main(String[] args) throws Exception {
        File file = new File("d:" + File.separator +"test.txt");
        if (file.exists()){
            file.delete();
        }else{
            System.out.println(file.createNewFile());
        }
    }
}

在JAVA的IO操作时,会出现延迟情况,因为现在的问题是JAVA间接调用 JVM,调用操作系统处理文件的方法,所以中间会出现延迟。

  • 找到父路径:public File getParentFile();
  • 创建目录:public boolean mkdirs();
    代码如下:
public class FileTestClass {
    public static void main(String[] args) throws Exception {
        File file = new File("d:" + File.separator +"demo"+File.separator+"tset"+File.separator+"gysh"+File.separator+"test.txt");
        if ( !file.getParentFile().exists() ){
            file.getParentFile().mkdirs();
        }
        if(file.exists()) {
            file.delete();
        }else
        {
            System.out.println(file.createNewFile());
        }
    }
}

在File类里面还提供有一系列的取得文件信息内容的操作功能:

  • 取得文件大小:public long length(); 按照字节返回
  • 判断是否是文件:public boolean isFile();
  • 判断是否是目录 :public boolean isDirectory();
  • 最近一次修改日期:public long lastModified(); 返回的是long型的日期,需要通过Date构造方法的来设置。
    以上所有操作是围绕文件进行的,但是在整个磁盘上除了文件之后,还有我们使用的目录,对于目录而言,最常用的功能是列出目录组成:
  • 列出目录下的信息:public String[] list();只列出目录或者文件名称
  • 列出所有的信息,以File类进行包装:public File[] listFile(); 这个列出目录下面的所有文件的信息,都是绝对路径。
    代码如下
public class DirectoryTestClass {
    public static void main(String[] args) throws Exception{
        File file = new File("D:"+File.separator+"03EBook");
        print(file);
    }
    //通过递归的方式,展示给定目录下所有文件的信息(绝对路径)
    public static void print(File file){
        if (file.isDirectory()){
            File result[] = file.listFiles();
            if(result!=null){
                for (int i = 0; i < result.length; i++) {
                    print(result[i]);
                }
            }
        }
        System.out.println(file);
    }
}

总结

  • File类只是对文件进行操作,而不对内容进行操作。
  • 目录分割符一定要用File.separator

2.2 内容操作(字节流、字符流)

如果要进行输入、输出操作一般都会按照如下步骤进行(以文件操作为例):

  • 通过File类定义一个要操作文件的路径
  • 通过字节流或字符流的子类对象为父类对象实例化
  • 进行数据的读、写操作
  • 数据流属于资源操作,资源操作必须关闭
    对于JAVA.iO包中定义两种流:
  • 字节流:InputStream、OutputStream
  • 字符流:Reader、Writer

2.2.1 字节输出流:OutputStream

OutputStream是一个专门进行字节数据输出的一个类,这个类定义如下:

public abstract class OutputStream extends Object implements Closeable,Flushable;

从上面代码中它实现了两个接口:Closeable、Flushable。
其中Closeable接口:

public interface Closeable extends AutoCloseable{
public void close() throws IOException;
}

从上面可以看出:接口可以继承接口;

public interface Flushable{
public void flush() throws IOException;
}

在OutputStream类中提供了三个输出方法:

  • 输出单个字节:public abstract void write(int b) throws IOException;
  • 输出全部字节:public abstract void write(byte[] b) throws IOException;
  • 输出部分字节:public abstract void write(byte[] b ,int off,int len) throws
    IOExcetion;
    OutputStream是一个抽象类,需要通过子类进行实例化操作,一般情况下使用较多的是FileOutputStream对象;
  • 创建或覆盖已有文件:public FileOutputStream(File file) throws FileNotFoundException;
  • 文件内容追加:public FileOutputStream(File file,boolean append) throws FileNotFoundException;
    代码如下:
public class OutputStreamTestClass {
    public static void main(String[] args) throws Exception{

        File file = new File("d:"+File.separator+"test.txt");
        if (!file.getParentFile().exists()){
            file.getParentFile().mkdirs();
        }
        FileOutputStream fileOutput = new FileOutputStream(file);
    String str = "你好啊,整个世界!";
    byte[] bStr = str.getBytes();
    //采用字节数组进行输出
    //fileOutput.write(bStr);;
        //采用单个字节进行输出
        for (int i = 0; i < bStr.length; i++) {
            fileOutput.write(bStr[i]);
        }
        //采用部分数据输出
        //fileOutput.write(bStr,6,6);//一个汉字占用两个字节
    fileOutput.close();
    }
}

2.2.2 字节输入流:InputStream

如果程序需要进行读取操作,可以利用InputStream类实现此功能,

public abstract class InputStream extends Object implements Closeable;

这个不与OutputStream一样,不需要考虑Closeable这个接口的存在,还是需要手动去操作关闭。
InputStream主要的方法如下:

  • 读取单个字节:public abstract int read() throws IOException;
  • 将读取的数据保存在字节中:public int read(byte[] b) throws IOException;
  • 将读取的数据保存在部分字节数组里:public int read(byte[] b,int off,int len) throws IOException;
    Inputstream是一个抽象类,需要使用它对应的子类来实例化,对于文件读取,我们经常使用FileInputStream子类,代码如下:
public class InputStreamTestClass {
    public static void main(String[] args) throws IOException {
        File file = new File("d:"+File.separator+"test.txt");
        FileInputStream fileInput = null;
        if(file.exists()){
             fileInput = new FileInputStream(file);
        }
        byte[] b = new byte[1024];
       int len =  fileInput.read(b);
        fileInput.close();
        System.out.println("["+new String(b,0,len)+"]");
    }
}

2.2.3 字符输出和输入流(Reader、Writer)

Writer类:

public abstract class Writer extends Object implements Appendable,Closeable,Flushable;

Writer也是一个抽象类,需要有子类进行实例化,一般情况下使用FileWriter子类,它比OutputStream类多实现了一个接口,这个接口主要的方法有:

public interface Appendable{
public Appendable append(char c) throws IOException;
public Appendable append(CharSequence csq) throws IOException;
public Appendable append(CharSequence csq,int start,int end) throws IOException;
}

Appendable主要是追加字符或者字符串。
对于Writer类来说,主要功能如下:

  • 输出全部字符数组:public void write(char[] cbuf) throws IOException;
  • 输出字符串:public void write(String str) throws IOException;

对于Reader与InputStream基本一样,不在详细说明。

2.2.4 字节流与字符流的区别

  • 字节流是直接与终端进行交互,而字符流需要经过缓冲区处理之后才能与终端交流
  • 在使用OutputStream输出数据时,即使最后没有关闭输出流,那么内容也可以正常输出,如果使用的字符输出流,如果没有关闭,表示在缓冲区中处理的内容不会被强制性清空,不能正常输出,但是有一种特殊情况,不关闭输出流的情况,可以使用flush()方法可以强制清空缓冲区。
  • 对于字节数据处理的比较多,例如:图片、音乐、视频、文字等,可以处理中文数据。
  • 在处理中文相关的数据时,建议优先考虑使用字节流。

2.2.5 字节流与字符流之间转换

在java.io包里面提供有两个类:InputStreamReader、OutputStreamWriter两个转换类。

public class OutputStreamTestClass {
    public static void main(String[] args) throws Exception{

        File file = new File("d:"+File.separator+"test.txt");
        if (!file.getParentFile().exists()){
            file.getParentFile().mkdirs();
        }
        OutputStream fileOutput = new FileOutputStream(file);
        Writer out = new OutputStreamWriter(fileOutput);
        out.write("习主席万岁!!!");
        out.flush();
        out.close();

   /* String str = "你好啊,整个世界!";
    byte[] bStr = str.getBytes();
    //采用字节数组进行输出
    //fileOutput.write(bStr);;
        //采用单个字节进行输出
        for (int i = 0; i < bStr.length; i++) {
            fileOutput.write(bStr[i]);
        }
        //采用部分数据输出
        //fileOutput.write(bStr,6,6);//一个汉字占用两个字节*/
    fileOutput.close();
    }
}

3 字符编码

计算机中所有的信息组成都是二进制数据,那么如果需要描述出中文字符的需要进行编码处理,所有的语言都要通过使用编码来进行描述,那么在计算机语言中常见的编码如下

  • GBK、GB2312:中文的国标编码,其中GBK包含有简体和繁体中文,GB2312只包含简体。
  • ISO8859-1:是国际编码,可以描述任何的文字信息
  • UNICODE:是十六进制编码,造成传输时,无用数据过多,占用较大带宽
  • UTF编码(UTF-8):融合了ISO8859-1和UNICODE编码的特点
    在以后 的软件开发过程中,使用的都是UTF-8编码。
    所谓的乱码最本质的方式就是编码与解码的字符集不统一。

4 内存流

我们可以使用内存流实现IO操作。在字节、字符输入与输出流中讲解了对文件数据的输入与输出的操作,如果我们只是对数据操作,又不想产生文件,我们就可以利用内存流实现输入与输出的操作。
针对内存流,JAVA中提供了两组操作:

  • ByteArrayInputStream
  • ByteArrayOutputStream
  • CharArrayWriter
  • CharArrayReader
    下面主要讲解ByteArrayInputStream与ByteArrayOutputStream
    什么是输出与输入:
    以文件操作为例:是把文件当做终端
  • 输出(OutputStream):程序-》OutputStream-》文件
  • 输入(InputStream):程序《-InputStream《-文件
    以内存操作为例:是把程序当做终端
  • 输出(InputStream):程序-》InputStream-》内存
  • 输入(OutputStream):程序《-OutputStream《-内存
    代码如下:
public class MemoryStreamClass {
    public static void main(String[] args) throws Exception{
        String str = "Hello,World!!";
        InputStream input = new ByteArrayInputStream(str.getBytes());
        OutputStream output = new ByteArrayOutputStream();
        int temp =0;
        while ((temp = input.read()) != -1){
            output.write(Character.toUpperCase(temp));
        }
        System.out.println(output);
        input.close();
        output.close();
    }
}

对于ByteArrayOutputStream类中有一个方法能把内存中的数据转变成字节数组:
public byte[] toByteArray();
代码如下:

public class ToByteArrayTest {
    public static void main(String[] args) throws Exception {
        File fileA = new File("D:"+File.separator+"test.txt");
        File fileB = new File("D:"+File.separator+"testB.txt");
        InputStream fileinputA = new FileInputStream(fileA);
        InputStream fileInputB = new FileInputStream(fileB);
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int temp = 0;
        while((temp = fileinputA.read()) != -1){
            out.write(temp);
        }
        while((temp = fileInputB.read())!= -1){
            out.write(temp);
        }
        //通过下面的能够把两个文件的内容进行合并,并输出
        byte b[] = out.toByteArray();
        System.out.println(new String(b));
        fileinputA.close();
        fileInputB.close();
        out.close();;
    }
}

5 打印流

主要讲解打印流的实现原理以及打印流的操作类的使用,打印流在JAVA开发中是非常重要的一部分。
为了解决输出数据,能够输出各中格式,JAVA中提供了一个专门用来输出数据的类,分别是PrintStream、PrintWriter

  • PrintStream是用来打印字节流;
  • PrintWriter是用来打印字符流:
    PrintStream是基于OutputStream类设计而成的,通过对OutputStream进行包装(装饰模式)来完成的。
    代码如下:
public class PrintStreamClass
{
    public static void main(String[] args) throws  Exception{
        File file = new File("d:"+File.separator+"test.txt");
        PrintStream ps = new PrintStream(new FileOutputStream(file));
        ps.print(false);
        ps.println();;
        ps.println(23);
        ps.println(23.45);
        ps.println("你好!");
    }
}

在以后开发过程中,如果有程序输出模式,都会采用 打印流的模式,一定要知道打印流也是基于OutputStream的类完成实现功能。
打印流是在JDK1.5之后,进行设计 ,被称为格式化输出:public PrintStream printf(String format,Object … args);

6 System类对IO的支持

在System类里面为了支持IO操作专门提供有三个常量:

  • 错误输出:public static final PrintStream err;
  • 输出到标准输出设备(显示器):public static final PrintStream out;
  • 从标准输入设备读取数据:public static final InputStream in;
    其中:
    System.err这个不经常使用,它和System.out中的功能是一样的。
    System.in
public class SystemInClass {
    public static void main(String[] args) throws Exception {
        InputStream input = System.in;
        byte[] b = new byte[1024];
        System.out.print("请输入数据:");
        int len = input.read(b);
        System.out.println("输入的数据是:"+new String(b,0,len));

    }
}

7 缓冲流

如果要进行中文数据处理,首先我们会使用字符流,并且要完整的处理数据,需要利用缓冲区的操作,在JAVA中对缓冲区操作有两种流:

  • 字符缓冲区流:BufferedReader、BufferedWriter
  • 字节缓冲区流:BufferedInputStream、BufferedOutputStream
    其中在BufferedReader类是非常重要,是因为它提供了一个重要的方法:public String readLine() throws IOException;
    代码如下:
public class BufferedReaderTest {
    public static void main(String[] args) throws IOException {
        //通过转换流把字节流转换到字符流
        BufferedReader buffer = new BufferedReader(new InputStreamReader(System.in));
        System.out.print("请输入数据:");
        String str = buffer.readLine();
        System.out.println("数据输入的内容是:"+str);
    }
}

结合正则表达式来判断输入数据是否为年龄数字,代码如下:

public class RegexStreamTest {
    public static void main(String[] args) throws IOException {
        BufferedReader buffer = new BufferedReader(new InputStreamReader(System.in));
        boolean flag = true;
        while (flag){
            System.out.println("请输入年龄数据:");
            String str = buffer.readLine();
            if(str.matches("\\d{1,3}")){
                System.out.println("年龄是:"+Integer.parseInt(str));
                flag =false;
            }else
            {
                System.out.println("输入的年龄数据是错误的!");
            }
        }

    }
}

利用BufferReader也可以对文件进行读取,一行一行的读取。
读取数据不再直接使用InputStream,就好比不使用OutputStream一样。

8 扫描流

主要讲解Scanner类的主要特点以及操作形式,利用Scanner来解决数据输入流的操作。
对于改进输出流的不足提供了打印流,对于文件内容行读取,又提供了BufferedReader类,解决了读取大文件的问题。
那么如何解决输入的功能不足:主要由Scanner提供,这个类在java.util包中,真正解决所有的输入流的一个工具。
Scanner类的构造方法:public Scanner(InputStream source);接收一个InputStream输入流。
JAVA在Scanner类中定义了两组方法:

  • 判断是否有指定数据:public boolean hasNextXxx();
  • 取出数据:public String nextXxx();
    代码如下:
public class ScannerTest {
    public static void main(String[] args) {
        Scanner s = new Scanner(System.in);
        while (s.hasNext()){
            System.out.println(s.next());
        }
        s.close();
    }
}

Scanner类结合正则表达式,能够判断输入数据的格式 ,代码如下:

public class ScannerTest {
    public static void main(String[] args) {
        Scanner s = new Scanner(System.in);
     /*   while (s.hasNext()){
            System.out.println(s.next());
        }*/
        System.out.print("请输入生日:");
        if(s.hasNext("\\d{4}-\\d{2}-\\d{2}")){
            String str = s.next("\\d{4}-\\d{2}-\\d{2}");
            System.out.println("输入内容:"+str);

        }else{
            System.out.println("输入的不是数字,错误!!");
        }
        s.close();
    }
}

总结

猜你喜欢

转载自blog.csdn.net/gyshun/article/details/84570417