GVKun编程网logo

java基础——随机访问流(java随机访问文件功能)

21

在本文中,我们将为您详细介绍java基础——随机访问流的相关知识,并且为您解答关于java随机访问文件功能的疑问,此外,我们还会提供一些关于java基础——IO、Java基础——代码块、Java基础—

在本文中,我们将为您详细介绍java基础——随机访问流的相关知识,并且为您解答关于java随机访问文件功能的疑问,此外,我们还会提供一些关于java基础——IO、Java基础——代码块、Java基础——值传递、JAVA基础——内存流的有用信息。

本文目录一览:

java基础——随机访问流(java随机访问文件功能)

java基础——随机访问流(java随机访问文件功能)

package stream;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;

import org.junit.jupiter.api.Test;



/*
 * RandomAccessFile:随机读写访问流
 *     既可以是输入流,也可以是输出流
 *     r|w|d|s:读|写|更新数据|元数据更新 
 *     
 *     w:是对开头对文件内容进行覆盖
 * 
 * */

public class RandomAccessFileTest {
    
    @Test
    public void test1(){
        
        RandomAccessFile raf1 = null;
        RandomAccessFile raf2 = null;
        try {
            //1.流对象
            raf1 = new RandomAccessFile(new File("hello.txt"),"r");
            raf2 = new RandomAccessFile(new File("hello2.txt"),"rw");
            
            //2.读写
            byte[]     buffer = new byte[1024];
            int len;
            while((len = raf1.read(buffer))!=-1) {
                raf2.write(buffer,0,len);
            }
        } catch (Exception e) {
            
            e.printStackTrace();
        }
        finally {
            try {
                if(raf1!=null)
                    raf1.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                if(raf2!=null)
                    raf2.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    /*
     * seek随机访问|插入方法
     * 
     * */
    @Test
    public void test2() throws IOException {
        RandomAccessFile raf1 = new RandomAccessFile("hello.txt", "rw");
        /*raf1.seek(3); 
        raf1.write("abc".getBytes());
        */
        
        /*
         * 使用StringBuilder
         * */
        StringBuilder sb = new StringBuilder((int)(new File("hello.txt").length()));
        raf1.seek(3L);
        int len;
        byte[] buffer = new byte[20];
        //把后面的存起来
        while((len = raf1.read(buffer))!=-1) {
            sb.append(new String(buffer,0,len));
        }
        
        raf1.seek(3L);
        //转换成字节写入
        raf1.write("周恩杰".getBytes());
        raf1.write(sb.toString().getBytes());
        raf1.close();
    }
}

java基础——IO

java基础——IO

java类库创建了大量的io类来满足各种io端相互通信的需求。io是以流的输入输出为基础的,屏蔽了各种设备的实现细节。

一、InputStream

InputStream为输入流的基类,它的子类表示了不同数据源的输入流。

  1. 数据源为字节数组ByteArrayInputStream.可以作为内存缓冲区,从里面读取字节。
  2. 数据源为String对象的StringBufferInputStream,将字符串转换成输入流。
  3. 数据源为文件的FIleInputStream.
  4. "管道"PipedInputStream作为多线程的数据源,一端输入,另一端输出。
  5. SequenceInputStream将多个输入流合并成一个流。
  6. 其他数据源,如internet.

在使用InputStream时很少使用单一的流对象,而是使用装饰器输入流FilterInputStream组合多个对象来使用。FilterInputStream类型:

  1. DataInputStream可以以流的形式读取基本数据类型(int,char,long等)。
  2. BufferedInputStream代表使用"缓冲区"进行读取。
  3. LineNumberInputStream跟踪输入流中的行号,使用getLineNumber()和setLineNumber(int numer).
  4. PusheBackInputStream具有"能弹出一个字节的缓冲区",可以将最后读到的一个字节回退,通常作为编译器的扫描器。

 

二、OutputStream

OutputStream为输出流的基类,它的子类表示了不同数据源的输出流,输出流决定了输出的目标:字节数组、文件、管道。

  1. ByteArrayOutputStream为要输出的"流"的数据在内存中创建缓冲区。
  2. FileOutputStream文件输出流。
  3. PipedInputStream管道输出流。

而OutputStream一般也使用FilterOutputStream来组合多个对象提供输出功能。FilterInputStream类型:

  1. DataOutputStream与DataInputStream对应,想输出流中写入基本数据类型。
  2. PrintStream格式化输出。
  3. BufferedOutputStream表示使用"缓冲区"输出数据,可以用flush()清空缓冲区。可以指定缓冲区大小。

三、Reader和Writer

Reader和Writer提供了字符的输入和输出功能,InputStreamReader可以把InputStream转换为Reader,OutputStreamWriter可以把OutputStream转换为Writer。他们之间的具体转换如下:

InputStream Reader,适配器:InputStreamReader
OutputStream Writer,适配器:OutputStreamWriter
FileInputStream FileReader
FileOutputStream FileWriter
StringBufferInputStream StringReader
无对应 StringWriter
ByteArrayInputStream CharArrayReader
ByteArrayOutputStream CharArrayWriter
PiedInputStream PiedReader
PiedOutputStream PiedWriter

四、RandomAccessFile

RandomAccessFile不是InputStream或OutputStream的继承,而是一个独立的文件读写类,适用于大小已知的记录组成的文件,可以用seek()方法将记录从一处转到另一处。同时它支持搜索方法,并且只适用于文件。1.4后它的大部分功能由nio存储映射文件替代

五、nio

nio使用缓冲器ByteBuffer在通道之间传输数据,i/o中有三个类可以产生FileChannal,分别是FileInputStream,FileOutputStream和RandomAccessFile.可以向通道传递用于读写的ByteBuffer.

六、aio

Java基础——代码块

Java基础——代码块

代码块:在类或方法中直接使用 “{ }”括起来的一段代码,表示一块代码区域。

代码块里变量属于局部变量,只在自己所在区域{ }内有效。

代码块依据位置不同分为三种形式:

  • 局部代码块:直接定义在方法内部的代码块。一般不直接使用,常结合if /for语句中使用的局部代码块。

    局部代码块程序示例:

    public class CodeBlock {
    
    	public static void main(String[] args) {
    	
    		int a=1;
    		{
    			int b=2;
    			System.out.println(a);
    			System.out.println(b);
    		}
    		System.out.println(a);
    		
    		// System.out.println(b);  //此处b无法输出
    	}
    
    }

    局部代码块程序示例运行结果:

    1
    2
    1
  • 初始化代码块(构造代码块):直接定义在类中。每次创建对象都会执行初始化代码块,每次创建对象都会调用构造器。在调用构造器之前,会先执行本类中的初始化代码块。(通过反编译后,会发现初始化代码块也作为构造器的最初语句。)

 

    

        

        初始化码块程序示例:

  • public class CodeBlock {
    
    	{
    		System.out.println("初始化代码块##########");
    	}
    	
    	CodeBlock(){		//构造器
    		System.out.println("构造器!!!!!!!!!");
    	}
    	public static void main(String[] args) {
    	
    		new CodeBlock();
    		System.out.println("~~~~~~~~~~~");
    		new CodeBlock();
    		
    	}
    
    }
    

     初始化码块程序示例运行结果:

    初始化代码块##########
    构造器!!!!!!!!!
    ~~~~~~~~~~~
    初始化代码块##########
    构造器!!!!!!!!!

               

  • 静态代码块(使用static修饰的代码块):在主方法执行之前执行静态代码块,且执行一次。

  静态代码块程序示例:

 

public class CodeBlock {

	{
		System.out.println("初始化代码块##########");
	}
	
	CodeBlock(){		//构造器
		System.out.println("构造器!!!!!!!!!");
	}
	
	static{		//静态代码块A
		System.out.println("静态代码块A:$$$$$$$$$$");
	}
	
	public static void main(String[] args) {
	
		new CodeBlock();
		System.out.println("~~~~~~~~~~~");
		new CodeBlock();
		
	}
	
	static{		//静态代码块B
		System.out.println("静态代码块B:$$$$$$$$$$");
	}

}

 

        静态代码块程序示例运行结果:

静态代码块A:$$$$$$$$$$
静态代码块B:$$$$$$$$$$
初始化代码块##########
构造器!!!!!!!!!
~~~~~~~~~~~
初始化代码块##########
构造器!!!!!!!!!

 

      

Java基础——值传递

Java基础——值传递

值传递?

参数传递的值的拷贝,改变拷贝不影响原参数。

引用传递?

参数传递的是参数本身,改变形参,实参也改变。

Java中是什么传递?

Java中只有值传递

实际情况为什么不对呢?

  1. 基本数据类型

  

 1 public class Main {
 2 
 3 
 4     void method01(int a ){
 5         a++;
 6         System.out.println("a in method01 is "+a);
 7     }
 8 
 9     public static void main(String[] args) {
10        Main main = new Main();
11        int a = 12;
12        
13        main.method01(a);
14        System.out.println(a);
15 
16 
17     }
18 }

输出结果:

a in method01 is 13
12

没有问题,原值没有改变。

  2. String类型

 1 public class Main {
 2 
 3     void method02(String s){
 4         s = "world";
 5         System.out.println("string in method is "+s);
 6    
 7     }
 8 
 9 
10     public static void main(String[] args) {
11        Main main = new Main();
12    
13        String s = "hello";
14 
15        main.method02(s);
16        System.out.println(s);
17 
18 
19     }
20 }

输出结果:

string in method is world
hello

没有问题,是值传递。原值没有改变

  3. 自定义类

public class Main {
    void method03(Cat cat){
        cat.setName("haha");
        System.out.println("cats name is "+cat.getName());
    }

    public static void main(String[] args) {
       Main main = new Main();

        Cat cat = new Cat();
        cat.setName("mimi");
        main.method03(cat);
        System.out.println("cats name in main is "+cat.getName());

    }
}
class Cat{
    String name;

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

输出结果:

cats name is haha
cats name in main is haha

不对!为什么值传递原值改变了??????

注意了,这里虽然原值改变了,但是还是值传递。为什么呢?

因为传递的是参数的引用的拷贝也是值传递,这里的值指的是地址的拷贝。

这里举一个简单的例子(引用地址:https://www.cnblogs.com/wchxj/p/8729503.html)

值传递:你有一把钥匙,当你的朋友想要去你家的时候,你复刻了一把新钥匙给他,自己的还在自己手里,这就是值传递。这种情况下,他对这把钥匙做什么都不会影响你手里的这把钥匙。

引用传递:你有一把钥匙,当你的朋友想要去你家的时候,如果你直接把你的钥匙给他了,这就是引用传递。这种情况下,如果他对这把钥匙做了什么事情,比如他在钥匙上刻下了自己名字,那么这把钥匙还给你的时候,你自己的钥匙上也会多出他刻的名字。

当你使用值传递,拷贝一份钥匙给你朋友后,你朋友在你家砸了电视,那么你回家的时候电视肯定是被砸了的。

这个例子理解起来就容易多了。按照这个逻辑我们来测验一下。

如果Java传递的只是引用的拷贝的话,我们将形参指向null,那么实参不会受到影响。通过上面的例子来解释就是,如果你给你朋友的钥匙只是一把复制的钥匙的话,我们将朋友手上的钥匙摧毁,我们还是能通过钥匙原件开门。

 

public class Main {

    void method04(Cat cat){
    //摧毁朋友手中的钥匙 cat
= null; try { System.out.println(cat.getName()); }catch (Exception e){ e.printStackTrace(); System.out.println("cat 已经被回收!"); } } public static void main(String[] args) { Main main = new Main(); Cat cat = new Cat(); cat.setName("mimi"); main.method04(cat); System.out.println(cat.getName()); } } class Cat{ String name; public void setName(String name) { this.name = name; } public String getName() { return name; }

输出结果:

java.lang.NullPointerException
at Main.method04(Main.java:21)
at Main.main(Main.java:44)
cat 已经被回收!
new name

没错!就是这样。

所以Java中只有值传递。

JAVA基础——内存流

JAVA基础——内存流

掌握内存操作流

输入和输出都是从文件中来的,当然,也可将输出的位置设置在内存上,这就需要ByteArrayInputStream和ByteArrayOutputStream

ByteArrayInputStream:将内容写入到内存中

ByteArrayOutputStream:将内存中数据输出

此时的操作应该以内存为操作点。

利用此类 完成一些功能。


 

常用方法

ByteArrayInputStream :是InputStream子类。

public class ByteArrayInputStream extends InputStream

构造方法:

ByteArrayInputStream(byte[] buf) 
          创建一个 ByteArrayInputStream,使用 buf 作为其缓冲区数组。

接收一个byte数组,实际上内存的输入就是在构造方法上将数据传递到内存之中。

ByteArrayOutputStream:是OutputStream子类

输出就是从内存中写出数据。

public class ByteArrayOutputStream extends OutputStream

构造方法:

ByteArrayOutputStream() 
          创建一个新的 byte 数组输出流。

主要方法:

void write(int b) 
          将指定的字节写入此 byte 数组输出流。

利用他们,完成一个大小写字母转换顺序的程序。

重温一下这个方法:getBytes();定义如下:返回的是一个byte类型的数组。 

    public byte[] getBytes() {
        return StringCoding.encode(value, 0, value.length);
    }

1,

int size() 
          返回缓冲区的当前大小

2,

byte[] toByteArray() 
          创建一个新分配的 byte 数组。

3,

String toString() 
          使用平台默认的字符集,通过解码字节将缓冲区内容转换为字符串

利用他们,完成一个大小写字母转换顺序的程序

String类的大小写转换方法:

String toLowerCase() 
          使用默认语言环境的规则将此 String 中的所有字符都转换为小写。

转大写:

String toUpperCase() 
          使用默认语言环境的规则将此 String 中的所有字符都转换为大写。

如果要想把一个大写边小写,则可以通过包装类,字符的包装类是Character

static char toLowerCase(char ch) 
          使用取自 UnicodeData 文件的大小写映射信息将字符参数转换为小写。

 

代码实例:

注意,跟文件读取不一样,不要设置文件路径

复制代码
复制代码
package 类集;
import java.io.* ;
public class ByteArrayDemo01{
    public static void main(String args[]){
        String str = "HELLOWORLD" ;        // 定义一个字符串,全部由大写字母组成
        ByteArrayInputStream bis = null ;    // 内存输入流
        ByteArrayOutputStream bos = null ;    // 内存输出流
        bis = new ByteArrayInputStream(str.getBytes()) ;    // 向内存中输出内容,注意,没有跟文件读取一样,设置文件路径。
        bos = new ByteArrayOutputStream() ;    // 准备从内存ByteArrayInputStream中读取内容,注意,跟文件读取不一样,不要设置文件路径
    int temp = 0 ;       while((temp=bis.read())!=-1)     {        char c = (char) temp ; // 读取的数字变为字符         bos.write(Character.toLowerCase(c)) ; // 将字符变为小写       } // 所有的数据就全部都在ByteArrayOutputStream中       String newStr = bos.toString() ; // 因为所有output的数据都在ByteArrayOutputStream实例对象中,所以可以取出内容,将缓冲区内容转换为字符串
    try{          bis.close() ;          bos.close() ;       }catch(IOException e){          e.printStackTrace() ;      } System.out.println(newStr) ;     } };
复制代码
复制代码

实际上以上操作很好体现了对象的多态。通过实例化其子类不同,完成的功能也不同,也就相当于输出的位置不同,

如果是输出文件,则使用FileXxxx类。如果是内存,则使用ByteArrayXxx。

关于java基础——随机访问流java随机访问文件功能的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于java基础——IO、Java基础——代码块、Java基础——值传递、JAVA基础——内存流等相关知识的信息别忘了在本站进行查找喔。

本文标签: