Java IO_002.InputStream与OutputStream--字节流对数据的操作(读取与写入)
Java IO之FileInputStream与FileOutputStream对象常用操作
涉及到文件(非文件夹)内容的操作,除了要用到File(见之前文章),另外就必须用到输入流或输出流。
输入流:该流处理时,数据由外部流向程序(内存),一般指代“读取数据”,更清晰点地说:从外部读取数据到内存中。
输出流:该流处理时,数据由程序(内存)流向外部,一般指代“写入数据”,更清晰点地说:将数据从内存写入到外部。
如果要操作字节(比如Soket,字节数据、图片、视屏等非纯文本文件),则采用字节输入流与字节输出流。在Java中,可使用: InputStream 与 OutputStream 及其子类。
如果要操作字符(比如字符数据、纯文本文件),则采用字符输入流与字符输出流。在Java中,可使用:Reader 与 Writer 及其子类。
对字节的操作,采用 InputStream与OutputStream。它们的为声明分别为:
public abstract class InputStream implements Closeable
public abstract class OutputStream implements Closeable, Flushable
它们都是抽象类,需要由具体子类进行实例化。
InputStream主要子类有:
- AudioInputStream:读取音像媒体的字节流。
- ByteArrayInputStream:读取字节数组的字节流。
- FileInputStream:读取文件的字节流。
- FilterInputStream:过滤器输入流,用于装饰。其子类有:PushbackInputStream , BufferedInputStream
- ObjectInputStream:读取序列化的对象的字节流。
- PipedInputStream:读取管道的字节流。
- SequenceInputStream:读取序列的字节流。
- PushbackInputStream:读取可以推回的字节流。继承自:FilterInputStream
- BufferedInputStream:读取有缓存效果的字节流。继承自:FilterInputStream
- StringBufferInputStream:读取字符缓冲的字节流。已过时,不作介绍。
常用的有FileInputStream,我们将以它为例。
OutputStream主要子类有:
- ByteArrayOutputStream:将字节写入到字节数组
- FileOutputStream:将字节写入到文件
- FilterOutputStream:过滤器输出流,用于装饰
- ObjectOutputStream:将字节写入到序列化对象
- PipedOutputStream:将字节写入管道
常用的有FileOutputStream,我们将以它为例。
InputStream与OutputStream的方法
InputStream字节输入流,其主要方法有:
int available():获取可用的字节总长度。返回int类型,该方法只要用于获取可被后续线程使用的流的长度,并且随已读取字节的变化而变化(见下边例子),特别是用它来表示文件大小时并不可靠(因为特大文件的字节长度可能是long字节。对于文件字节数,可以使用file.length()来代替)。
void close():释放流对象。用于关闭资源。close()后无法进行read及skip等操作。所以一般在流操作结束后进行close()调用。
void mark(int readlimit):标记流的位置。系统不一定支持。不推荐使用。
boolean markSupported():检测是否支持流位置标记。(mark方法与reset方法在其支持下才可用。一般能不用则不用此3个方法)
abstract int read():从流中读取一个字节,如果没有数据,返回-1。
int read(byte[] b):从流中读取字节,并将数据存入到指定的字节数组中,读取的字节数为指定数组的长度。如果没有数据,返回-1。
int read(byte[] b, int off, int len):从流中读取字节,并将数据存入到指定的字节数组中,读取的字节数为len,存入时从数组off开始存。如果没有数据,返回-1。
void reset():从新设置流的开始。系统不一定支持。不推荐使用。
long skip(long n):跳过指定数目字节。可以是正数负数或0(对于文件流来说,该方法已被重载,可以用来解决系统不支持reset()问题。负数是往回转跳,0不进行转跳。)。
输入字节流InputStream用于“读取”,其中最常用的方法是:read(), read(byte[] b), read(byte[] b, int off, int len)
综合测试代码:
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream; public class File001 {
public static void main(String[] args) throws IOException {
File file = new File("g:/java2019/file.txt");//文件内容:abc //打开流
InputStream is = new FileInputStream(file);
long len = file.length();
System.out.println("available:"+is.available());
System.out.println(is.read());//读取第一个字节:a
System.out.println(is.read());//读取第一个字节:b
System.out.println(is.read());//读取第一个字节:c
System.out.println(is.read());//-1
System.out.println(is.read());//-1
System.out.println(is.read());//-1 System.out.println("available:"+is.available()); if(is.markSupported()){
System.out.println("IO支持标记,可以进行重定位到开头标记处。");
is.reset();
}else{
System.out.println("IO不支持标记,不可以进行重定位到开头标记处。使用回跳处理。");
is.skip(-len);
} for(int i=0;(i=is.read())!=-1;){
System.out.println(i);
} is.skip(-len); byte[] b3 = new byte[3];
int len2 = is.read(b3,0,1);//从流中读取1个字节,存在b3字节数组中,从b3的0位置开始存。
System.out.println("读取长度为::"+len2);
System.out.println("first byte:"+b3[0]); is.skip(-1);
is.read(b3);//从流中读取b3字节数组对应大小的字节存入b3中。
for(byte b : b3){
System.out.println(b);
} //关闭流
is.close();
} }
输出:
available:3
97
98
99
-1
-1
-1
available:0
IO不支持标记,不可以进行重定位到开头标记处。使用回跳处理。
97
98
99
读取长度为::1
first byte:97
97
98
99
说明:
- FileInputStream是文件字节输入流。其构造方法有:FileInputStream(File file) ,FileInputStream(String name), FileInputStream(FileDescriptor fdObj)。其中FileInputStream(String name)最为常用,它其实调用的也是FileInputStream(File file)。如果没有什么获取文件指定大小(需要用到File对象的length()方法:其实也可以通过name再构造一个File对象),推荐使用FileInputStream(String name),它最为简洁。
- FileInputStream对象一旦进行实例化,就会立刻进行文件的打开,所以如果文件不存在,会抛出FileNotFoundException异常(属于IOException)。所以该流使用结束后必须调用close()方法来进行关闭,进行资源释放。
- read()方法一次从文件输入流中读取一个字节,并返回int类型,并不返回byte类型,因为具体读取到的字节属于属于-128到127(占8位),直接返回的话,难以判定是读取到的字节数是-1,还是读取到结尾了,可能造成读取中断问题。所以返回int的话,会将8位的-1转化为32位int类型的255,避免冲突。read(byte[] b)以及read(byte[] b, int off, int len)方法一次读取数个字节,返回读取到的字节数,读取到结尾时返回-1。
- read()方法是阻塞的。即线程运行到read()处,该线程必须等待read()完成才能进行该线程后续代码执行操作。在网络通信状态不稳定或者socket等待时,往往配合多线程进行处理。read(byte[] b)以及read(byte[] b, int off, int len)同理。
- 对于文件流的读取,推荐使用read(byte[] b, int off, int len)来处理,可以减少读取次数,取得高效。
- for(int i=0;(i=is.read())!=-1;){} 块可用于循环读取输入流的字节,当读取到的结尾时返回-1。也可以用int i=0;while((i=is.read())!=-1){}块,效果同样(只是多了一行)。
OutputStream字节输入流,其主要方法有:
void close():释放流对象。用于关闭资源。close()后无法进行write及flush等操作。所以一般在流操作结束后进行close()调用。
void flush():刷新输出流,以便数据能够完全被写入。
void write(byte[] b):一次写入所给的字节数组的所有数据。
void write(byte[] b, int off, int len):一次写入所给的字节数组从off位置开始,长度为len的数据。
abstract void write(int b):一次写入一个字节。
输出字节流InputStream用于“写入”,其中最常用的方法是:write(byte[] b) , write(byte[] b, int off, int len) , write(int b)
测试代码:
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream; public class File002 {
public static void main(String[] args) throws IOException {
String filepath = "G:/java2019/file123.txt";
//打开文件构造输出流,如果文件不存在则进行创建,如果文件上级路径不存在,则抛出FileNotFoundException
OutputStream os = new FileOutputStream(filepath); os.write(97);//写入a
os.write(98);//写入b
os.write('c');//写入c byte[] b = new byte[]{97,98,99}; os.write(b); os.write(b, 2, 1);
os.write(b, 1, 1);
os.write(b, 0, 1); //关闭输出流
os.close(); //再次打开,需要再次构造。在文件内容后边进行写入。
os = new FileOutputStream(filepath, true);
String LINE = System.getProperty("line.separator");
byte[] bLine = null;
if(LINE.equals("\r")){
bLine = new byte[]{10};
}else if(LINE.equals("\n")){
bLine = new byte[]{13};
}else{// LINE.equals("\r\n")
bLine = new byte[]{10,13};
} //输出换行
os.write(bLine); os.write(new byte[]{'A','B','C'}); //关闭输出流
os.close(); }
}
文件内容:
abcabccba
(这时是空白行)
ABC
说明:
- FileOutputStream是文件字节输出流。其构造方法有:FileOutputStream(File file) ,FileOutputStream(File file, boolean append) ,FileOutputStream(String name),FileOutputStream(String name, boolean append), FileOutputStream(FileDescriptor fdObj)。其中FileOutputStream(String name)及FileOutputStream(String name, boolean append)最为常用,它其实调用的也是FileOutputStream(File file)或FileOutputStream(File file, boolean append)。如果没有什么获取文件指定大小(需要用到File对象的length()方法:其实也可以通过name再构造一个File对象),推荐使用FileoutputStream(String name)及FileOutputStream(String name, boolean append),它最为简洁。boolean类型的参数append指明对文件内容的写入是否要接在文件末尾,如果不想覆盖原来文件的内容,则需要使用FileOutputStream(name,true),因为默认情况下是false(会覆盖)。
- FileOutputStream对象一旦进行实例化,就会立刻进行文件的打开,所以如果文件不存在,会自动创建,如果文件所在路径(上级目录)不存在,会抛出FileNotFoundException异常(属于IOException)。所以该流使用结束后必须调用close()方法来进行关闭,进行资源释放。
- write(int b)方法一次向文件输出流中写入一个字节,int类型会最终转化为byte类型。write(byte[] b)以及write(byte[] b, int off, int len)方法一次写入数个字节。
- write()方法是不会阻塞的。wrie(byte[] b)以及write(byte[] b, int off, int len)同理。
- 对于文件流的写入,推荐使用write(byte[] b, int off, int len)来处理,可以减少写入次数,取得高效。
- byte[] b=new byte[1024*8];int len=0;while((len=is.read(b))!=-1){os.write(b,0,len);}块可以配合读取、写入操作,进行高效的文件的复制。
高效的字节文件复制操作代码:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream; public class File003 {
public static void main(String[] args) throws IOException {
String from = "G:/java2019/file.txt";
String to = "G:/java2019/file2.txt";
InputStream is = new FileInputStream(from);
OutputStream os = new FileOutputStream(to); byte[] b = new byte[1024*8];
int len = 0;
while((len=is.read(b))!=-1){
os.write(b, 0, len);
} is.close();
os.close();
}
}
IO中,要处理具体的异常,可以这样:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream; public class File004 {
public static void main(String[] args) {
String from = "G:/java2019/file.txt";
String to = "G:/java2019/file2.txt";
InputStream is = null;
OutputStream os = null;
try {
is = new FileInputStream(from);
os = new FileOutputStream(to); byte[] b = new byte[1024 * 8];
int len = 0;
while ((len = is.read(b)) != -1) {
os.write(b, 0, len);
} } catch (IOException e) {
e.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
} if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} }
}
不过这样很烦索,如果在JDK1.7及以上版本,可以使用try-resource改进,代码:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream; public class File005 {
public static void main(String[] args) {
String from = "G:/java2019/file.txt";
String to = "G:/java2019/file2.txt";
try (InputStream is = new FileInputStream(from);OutputStream os = new FileOutputStream(to);) {
byte[] b = new byte[1024 * 8];
int len = 0;
while ((len = is.read(b)) != -1) {
os.write(b, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} }
}
JAVA也提供了比较高效的内置缓存流:BufferedInputStream及BufferedOutputStream。其内置缓冲区大小默认为1024*8(如果需要改变,可以在构造的时候传入其它值)。它们直接由InputSteam及OutputStream构造,所有方法都与InputStream及OutputStream相同。不过不同的是对于OutputStream,其write()实际上是写入到缓冲区,然后判断缓冲区是否满了,如果满了则使用flush()刷新缓冲区,同时写入文件,如果最后一次的时候刚才未满,则不能保证是否写入,这样会造成断尾了。可以使用其flush()方法,或者当进行close()的时候,也会进行缓冲区的刷新及文件的写入(不过对于JDK1.7及以上版本使用try-resource处理异常的情况下,会自动进行close(),不太需要担心)
BufferedInputStream构造器:
public BufferedInputStream(InputStream in):以字节输入流构造缓冲输入流,默认1024*8的缓冲区,常用。
public BufferedInputStream(InputStream in, int size) :以字节输入流构造缓冲输入流,缓冲区大小由size指定。
BufferedOutputStream构造器:
public BufferedOutputStream(OutputStream out):以字节输出流构造缓冲输出流,默认1024*8的缓冲区,常用。
public BufferedOutputStream(OutputStream out, int size):以字节输出流构造缓冲输出流,缓冲区大小由size指定。
测试代码:
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException; public class File006 {
public static void main(String[] args) {
String from = "G:/java2019/file.txt";
String to = "G:/java2019/file2.txt";
try (BufferedInputStream is = new BufferedInputStream(new FileInputStream(from));
BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(to));) {
byte[] b = new byte[1024 * 8];
int len = 0;
while ((len = is.read(b)) != -1) {
os.write(b, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} }
}
说明:
可以知道,使用字节缓冲流处理输入输出的时候,跟之前的代码相比,只需要改变构造器就可以,其它代码可以一概不变,因为缓冲字节流使用的是字节流对象构造并且直接重写其所有方法。
要进行高效的字节流处理,一方面可以使用缓冲字节流,另一方面可以使用自己写的高效处理方法(同上边“字节文件的复制”)。推荐使用后者,更灵活,更高效。
除了InputStream与OutputStream的应用中,除了FileInputStream与FileOutputStream常用来处理文件,也可以处理字节数组,数据,序列对象,管道,字符缓冲等。
ByteArrayInputStream可以从字节数组中获取字节输入流数据,ByteArrayOutputStream可以将数据写入字节数组输出流。代码:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream; public class File007 {
public static void main(String[] args) {
byte[] b = new byte[] {97,98,99};
try(InputStream is = new ByteArrayInputStream(b); OutputStream os = new ByteArrayOutputStream()){
int i = 0;
while((i=is.read())!=-1){
os.write(i);
} System.out.println(os.toString());
} catch (IOException e) {
e.printStackTrace();
} }
}
DataInputStream可以从int,long,float,double,char,byte[],boolean等中获取字节输入流的数据,DataOutputStream可以将int,long,float,double,char,byte[],boolean等数据写入字节输出流。代码:
public class File007 {
public static void main(String[] args) {
byte[] b = new byte[] { 97, 98, 99, 100 };
try (DataInputStream is = new DataInputStream(new ByteArrayInputStream(b));
DataOutputStream os = new DataOutputStream(new FileOutputStream("g:/java2019/file.txt"))) {
char c = 0;
c = is.readChar();// 读取两个字节
os.writeChar(c);// 写入两个字节
System.out.println(c);
c = is.readChar();
os.writeChar(c);
System.out.println(c);
} catch (IOException e) {
e.printStackTrace();
} }
}
输出:
慢
捤
文件内容:abcd
ObjectInputStream可以从已经序列化的对象(对象相对应的某种格式化的文件)等中获取字节输入流的数据,DataOutputStream可以将序列化的对象(实现Serialiazable接口的对象)写入字节输出流(最终变成相应格式文件数据)。代码:
测试代码:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable; public class File008 {
public static void main(String[] args) {
try (ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("g:/java2019/file.txt"))) {
User user = new User();
user.setId(1);
user.setName("dreamyoung");
os.writeObject(user);
} catch (IOException e) {
e.printStackTrace();
} try(ObjectInputStream is = new ObjectInputStream(new FileInputStream("g:/java2019/file.txt"))){
try {
User user = (User)is.readObject();
System.out.println(user);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
} }
} class User implements Serializable{
private static final long serialVersionUID = 1L;
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
} @Override
public String toString() {
return "User [id=" + id + ", name=" + name + "]";
}
}
输出:
User [id=1, name=dreamyoung]
文件内容:
sr User I idL namet Ljava/lang/String;xp t
dreamyoung
说明:
- 对象序列化通常指的是将对象数据(不是类)保存到文件,其格式由JVM自动生成。而反序列化指的是从文件中读取数据生成对象。
- 要序列化的对象必须实现Serializable接口(通常还可以添加serialVersionUID),不然会出现 NotSerializableException 异常。
SequenceInputStream可以从已经一个或多个的输入流中顺序获取字节输入流的数据。需要注意的是,没有SequenceOutputStream。代码:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.SequenceInputStream; public class File009 {
public static void main(String[] args) {
//通过顺序流,将两个文件内容写入一个新文件
try (FileInputStream fis1 = new FileInputStream("g:/java2019/file1.txt");//文件内容:111
FileInputStream fis2 = new FileInputStream("g:/java2019/file2.txt");//文件内容:222
SequenceInputStream is = new SequenceInputStream(fis1, fis2);
FileOutputStream fos = new FileOutputStream("g:/java2019/file3.txt")) {
byte[] b = new byte[1024];
int len = 0;
while((len=is.read(b))!=-1){
fos.write(b,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} }
}
文件file3.txt内容:111222
要进行文件分割,必须配套PushbackInputStream类来使用,它可以使用 unread(int b) 或 unread(byte[] b) 或 unread(byte[] b, int off, int len)将已经读取的内容返送回去,对于分割读取后超过的内容,则可以不读取。注意默认只能返回读一个字节,如果要推回的内容长度比较大,还是建议指定长度,否则会出现Push back buffer is full异常。分割文件的代码:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PushbackInputStream;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List; public class File011 {
public static void main(String[] args) {
// 没有SequenceOutputStream,要分割文件,可以采用如下手段:
File file1 = new File("g:/java2019/file1.txt");
File file2 = new File("g:/java2019/file2.txt");
File file3 = new File("g:/java2019/file3.txt"); try (FileOutputStream fos1 = new FileOutputStream(file1);
FileOutputStream fos2 = new FileOutputStream(file2);
FileOutputStream fos3 = new FileOutputStream(file3);
PushbackInputStream fis = new PushbackInputStream(new FileInputStream("g:/java2019/file.txt"), 1024)) {
// file.txt内容:111111222222333333
byte[] b = new byte[5];// 缓冲数组大小,不大于分割文件大小
int splitSize = 6;// 分割文件大小
int len = 0;
List<FileOutputStream> list = Arrays.asList(fos1, fos2, fos3);
Iterator<FileOutputStream> it = list.iterator();
while (it.hasNext()) {
FileOutputStream fos = (FileOutputStream) it.next();
while (fos.getChannel().size() < splitSize && (len = fis.read(b)) != -1) {
int left = (int) fos.getChannel().size() + len - splitSize; if (left > 0) {// 读取后会超出
for(int i=0;i<left;i++){
fis.unread(b[len-left+i]);
}
//fis.skip(-left);
fos.write(b, 0, len - left);
} else {
fos.write(b, 0, len);
} System.out.println(fos.toString() + ":" + fos.getChannel().size());
}
} } catch (IOException e) {
e.printStackTrace();
} }
输出:
java.io.FileOutputStream@15db9742:5
java.io.FileOutputStream@15db9742:6
java.io.FileOutputStream@6d06d69c:5
java.io.FileOutputStream@6d06d69c:6
java.io.FileOutputStream@7852e922:5
java.io.FileOutputStream@7852e922:6
分割后各文件内容为:
file1.txt: 111111
file2.txt: 222222
file3.txt: 333333
PipedInputStream可以从管道中获取字节输入流数据,PipedOutputStream可以将数据写入管道输出流。将在网络编程的时候进行说明,本篇暂不介绍。
总结:
- FileInputStream与FileOutputStream可以以字节流形式处理文件,进行读取或写入操作。
- 要进行高效的字节流处理,可以使用内置的BufferedInputStream及BufferedOutputStream缓冲字节流,它可以处理各种InputStream及OutputStream(不仅仅是FileInputStream及FileOutputStream)
- 使用read(byte[] b, int off, int len)及write(byte[], int off, int len) 可以更高效的进行字节复制(可以替代缓冲字节流)
流
Java IO_002.InputStream与OutputStream--字节流对数据的操作(读取与写入)的更多相关文章
- java的InputStream和OutputStream的理解【转】
1.在java中stream代表一种数据流(源),javaio的底层数据元,---(想像成水龙头)2.任何有能力产生数据流(源)的javaio对象就可以看作是一个InputStream对象既然它能产生 ...
- java的InputStream和OutputStream的理解
注:参考链接:http://www.cnblogs.com/springcsc/archive/2009/12/03/1616187.html 1.在java中stream代表一种数据流(源),jav ...
- java socket InputStream和OutputStream
从java socket对象获取的InputSteam的read方法其实是对linux的recv()函数的调用,OutputStream也同理. 也就是说,InputStream和OutputStre ...
- 【转载】关于java 的InputStream和OutputStream的理解
关于InputStream和OutputStream的输入输出方向的理解 InputStream输入类,首先需要读取的内容转化成输入流,再从它那里进行读取,先关联源:之后过程中关联目的,这样形成了流: ...
- 【Python】python和json数据相互转换,json读取和写入,repr和eval()使用
python数据转换json 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import jso ...
- java 对excel操作 读取、写入、修改数据;导出数据库数据到excel
============前提加入jar包jxl.jar========================= // 从数据库导出数据到excel public List<Xskh> outPu ...
- Java基础(5):试用Array类对数据进行操作(Sort和toString方法)
Arrays 类是 Java 中提供的一个工具类,在 java.util 包中.该类中包含了一些方法用来直接操作数组,比如可直接实现数组的排序.搜索等 1. 排序 语法: Arrays.sort(数 ...
- java(jdk1.7) IO系列01之InputStream和OutputStream解析
1.InputStream和OutputStream简介 在java中InputStream和OutputStream分别代表字节输入流和字节输出流,表示以字节的方式来实现进程或者程序的通信,Inpu ...
- Java流对象:InputStream、OutputStream、Reader、Writer
流对象使用完一般要用close方法关闭.释放资源. InputStream 和OutPutStream 二者都是字节输入和输出的抽象父类,子字节为单位处理数据,每次读取.写入一个字节,适合处理二进制文 ...
随机推荐
- java数据结构——栈(Stack)
学习数据结构与算法是枯燥的,但只有坚持不懈的积累,才会有硕果累累的明天. /** * 继续学习Java数据结构 ————栈 * 栈的实现其实还是使用数组,只不过我们不能直接访问数组下标,而是通过一个指 ...
- Redis高级客户端Lettuce详解
前提 Lettuce是一个Redis的Java驱动包,初识她的时候是使用RedisTemplate的时候遇到点问题Debug到底层的一些源码,发现spring-data-redis的驱动包在某个版本之 ...
- SpringBoot定时任务,总有一款适合你
title: SpringBoot定时任务,总有一款适合你 date: 2019-09-28 16:19:10 tags: - springboot - 定时任务 categories: java - ...
- 商用hadoop集群的配置命令分布
角色 安装 hdfs配置 yarn配置 hdfs 格式化 启动yarn服务 启动hdfs服务 master yum install hadoop-hdfs-namenode yum install h ...
- 基于SpringBoot + Mybatis实现 MVC 项目
1.预览: (1)完整项目结构 (2) 创建数据库.数据表: [user.sql] SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- ...
- QT两个窗口相互切换
信号(signals)与槽(slots)是QT重要机制,例子使用了C++11 lambda表达式进行了信号与槽的连接. 实现两个窗口通过点击按钮完成互相切换,注意子窗口只能发送信号,不能处理,所有信号 ...
- 非对称加密openssl协议在php7实践
据网上资料,RSA加密算法是一种非对称加密算法.在公开密钥加密和电子商务中RSA被广泛使用.RSA是1977年由罗纳德·李维斯特(RON RIVEST).阿迪·萨莫尔(ADI SHAMIR)和伦纳德· ...
- struts 2.3.28+spring 4.2.5.RELEASE+hibernate 5.1.0.Final整合maven构建项目基本配置
第一次写博客,主要也是记录给自己看的,可能很多比较熟的地方就没注释 用maven构建,ssh框架都是选用的最新的release版(感觉还是不要用beta),环境jdk1.8 tomcat8.0 mys ...
- 基于Spring AOP实现的权限控制
1.AOP简介 AOP,面向切面编程,往往被定义为促使软件系统实现关注点的分离的技术.系统是由许多不同的组件所组成的,每一个组件负责一块特定的功能.除了实现自身核心功能之外,这些组件还经常承担着额外的 ...
- POJ - 2393Yogurt factory
The cows have purchased a yogurt factory that makes world-famous Yucky Yogurt. Over the next N (1 &l ...