1.文本文件复制
/*
将C盘下的一个文本文件复制到D盘下。
其实就是将C盘下的文件数据存储到D盘下的一个文件中
步骤:
1.在D盘中创建一个文件,用于存储C盘文件中的数据。
2.定义读取流和C盘文件关联
3.通过不断的读写完成数据存储。
4.关闭资源。
*/
//方法一
import java.io.*;
class CopyText {
public static void main(String[] args) throws IOException{
copy();
}
public static void copy(){
FileReader fr = null;
FileWriter fw = null;
try{
fr = new FileReader("c:\\demo.txt");
fw = new FileWriter("d:\\demoD.txt",true);
char[] buf = new char[1024];
int len = 0;
while((len=fr.read(buf))!=-1){
fw.write(buf,0,len);
}
}catch (IOException e){
throw new RuntimeException("读写失败");
}finally{
if(fr!=null)
try{
fr.close();
}catch (IOException e){
System.out.println(e.toString());
}
if(fw!=null)
try{
fw.close();
}catch (IOException e){
System.out.println(e.toString());
}
}
}
}
//方法二
/*
通过缓冲区复制一个文本文件。
*/
import java.io.*;
class CopyTextByBuf{
public static void main(String[] args){
BufferedWriter bufw = null;
BufferedReader bufr = null;
try
{
bufw = new BufferedWriter(new FileWriter("e:\\bufD.txt",true));
bufr = new BufferedReader(new FileReader("c:\\buf.txt"));
String line = null;//相当于中转站。
while((line=bufr.readLine())!=null)
{
bufw.write(line);
bufw.newLine();
bufw.flush();
}
}
catch (IOException e)
{
throw new RuntimeException("读写失败");
}
finally
{
if(bufw!=null)
try
{
bufw.close();
}
catch (IOException e)
{
throw new RuntimeException("写入关闭失败");
}
if(bufr!=null)
try
{
bufr.close();
}
catch (IOException e)
{
throw new RuntimeException("读取关闭失败");
}
}
}
}
2.二进制文件(图片,视频等)复制
/*
复制一个图片(不要拿字符流处理媒体文件,字符流只处理文字数据)
思路:
1.用字节读取流对象和图片关联
2.用字节写入流对象创建一个图片文件,用于存储获取到的图片数据。
3.通过循环读写,完成数据的存储
4.关闭资源。
*/
import java.io.*;
class CopyPic
{
public static void main(String[] args)
{
FileOutputStream fos = null;
FileInputStream fis = null;
try
{
fos = new FileOutputStream("CopyofSrc.png");
fis = new FileInputStream("src.jpg");
byte[] buf = new byte[fis.available()];//定义一个刚刚好的缓冲区,不用再循环了。
int len = 0;
while((len = fis.read(buf))!=-1)
{
fos.write(buf);
}
}
catch (IOException e)
{
throw new RuntimeException("读写失败");
}
finally
{
try
{
if(fos!=null)
fos.close();
}
catch (IOException e)
{
throw new RuntimeException("写入失败");
}
try
{
if(fis!=null)
fis.close();
}
catch (IOException e)
{
throw new RuntimeException("读取失败");
}
}
}
}
3.标准键盘读取/标准控制台输出
//读取键盘输入的最常见写法。
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
//写入控制台的最常用写法。
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
4.UDP
/*
编写一个聊天程序
有收数据的部分和发数据的部分
这两部分需要同时执行,那就需要用到多线程技术,
一个线程控制接收,一个线程控制发送。
因为收和发动作是不一致的,所以要定义两个run方法,
而且这两个方法要封装到不同的类中。
*/
import java.io.*;
import java.net.*;
class Send implements Runnable
{
private DatagramSocket ds ;
public Send(DatagramSocket ds)
{
this.ds = ds;
}
public void run()
{
try
{
BufferedReader bufr =
new BufferedReader(new InputStreamReader(System.in));
String line = null;
while((line = bufr.readLine())!= null)
{
if("886".equals(line))
break;
byte[] buf = line.getBytes();
DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("localhost"),10003);
ds.send(dp);
}
}
catch (Exception e)
{
throw new RuntimeException("发送端失败");
}
}
}
class Rece implements Runnable
{
private DatagramSocket ds ;
public Rece(DatagramSocket ds)
{
this.ds = ds;
}
public void run()
{
try
{
while(true)
{
byte[] buf = new byte[1024*64];
DatagramPacket dp = new DatagramPacket(buf,buf.length);
ds.receive(dp);
String ip = dp.getAddress().getHostAddress();
String data = new String(dp.getData(),0,dp.getLength());
System.out.println(ip+":"+data);
}
}
catch (Exception e)
{
throw new RuntimeException("接收端失败");
}
}
}
class ChatDemo //必须掌握
{
public static void main(String[] args) throws Exception
{
DatagramSocket sendSocket = new DatagramSocket();
DatagramSocket receSocket = new DatagramSocket(10003);
new Thread(new Send(sendSocket)).start();
new Thread(new Rece(receSocket)).start();
}
}
5.TCP
/*
需求:客户端并发上传图片
*/
/*
客户端
1.服务端点
2.读取客户端已有的图片数据
3.通过socket输出流将数据发给服务端
4.读取服务端反馈信息
5.关闭
*/
import java.io.*;
import java.net.*;
class UploadPicClient
{
public static void main(String[] args) throws IOException
{
//主函数传参数 java UploadPicClient c:\1.png
if(args.length!=1)
{
System.out.println("请选择一个jpg格式的图片文件");
return;
}
File file = new File(args[0]);
if(!(file.exists()&&file.isFile()))
{
System.out.println("上传的文件不存在或者不是文件");
return ;
}
if(!(file.getName().endsWith(".png")))
{
System.out.println("上传的文件格式不正确,请重新选择!");
return;
}
if(file.length()>1024*1024*5)
{
System.out.println("文件过大,不安好心,重新选择 !");
return;
}
Socket s = new Socket("localhost",50005);
FileInputStream in = new FileInputStream(file);
OutputStream out = s.getOutputStream();
byte[] buf = new byte[1024];
int len = 0 ;
while((len = in.read(buf))!=-1)
{
out.write(buf,0,len);
}
//告诉服务器数据写完了。
s.shutdownOutput();
InputStream is = s.getInputStream();
byte[] bufIn = new byte[1024];
int num = is.read(bufIn);
System.out.println(new String(bufIn,0,num));
s.close();
in.close();
}
}
/*
服务端
这个服务端有个局限性,当A客户端连接上以后,被服务端获取到,服务端执行具体流程。
这时B客户端连接,只有等待
因为服务端还没有处理完A客户端的请求,还要循环回来执行下次accept方法,所以
暂时获取不到B客户端对象。
那么为了可以让多个客户端同时并发访问服务端,
那么服务端最好就是将每个客户端封装到一个单独的线程中,这样,就可以
同时处理多个客户端请求。
如何定义线程呢?
只要明确了每一个客户端要在服务端执行的代码即可,将该代码存入run方法中。
*/
class PicThread implements Runnable
{
private Socket s ;
PicThread(Socket s )
{
this.s = s;
}
public void run()
{
String ip = s.getInetAddress().getHostAddress();
int num = 1;//只能定义在函数内,在外的话是共享数据,不行的。
try
{
System.out.println(ip+".....connected");
InputStream in = s.getInputStream();
File file = new File("d:\\server.png");
while(file.exists())
file = new File("d:\\server("+(num++)+").png");
FileOutputStream out = new FileOutputStream(file);
byte[] buf = new byte[1024];
int len = 0 ;
while((len = in.read(buf))!=-1)
{
out.write(buf,0,len);
}
OutputStream os = s.getOutputStream();
os.write("上传图片成功!!".getBytes());
out.close();
s.close();
}
catch (Exception e)
{
throw new RuntimeException(ip+"上传失败^_^");
}
}
}
class UploadPicServer
{
public static void main(String[] args) throws IOException
{
ServerSocket ss = new ServerSocket(50005);
while(true)
{
Socket s = ss.accept();
new Thread(new PicThread(s)).start();//服务器多线程玩法,几乎所有服务器都这么玩。
}
}
}
6.多线程实现方式
//方法一:
/*
创建两个线程,和主线程交替运行
线程都有自己默认的名称
Thread-编号 该编号从0开始
static Thread currentThread():获取当前线程对象。
getName():获取线程名称。
设置线程名称:setName或者通过构造函数
*/
class Test extends Thread
{
public Test(String name)
{
super(name);//通过构造函数给线程取名。
}
public void run(){
for(int x = 0;x <10;x++)
{
System.out.println((Thread.currentThread()==this)+"...."+this.getName()+"run..."+x);
}
}
}
class ThreadTest
{
public static void main(String[] args)
{
Test t1 = new Test("one----");
Test t2 = new Test("two++++");
t1.start();
t2.start();
for(int i = 0 ;i<20;i++)
System.out.println("hello world"+i);
}
}
//方法二
class Ticket implements Runnable
{
private int tick = 10;
public void run()
{
while(true)
{
if(tick>0)
{
System.out.println(Thread.currentThread().getName()+"sale:"+tick--);
}
}
}
}
class TicketDemo
{
public static void main(String[] args)
{
Ticket t = new Ticket();
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
Thread t3 = new Thread(t);
Thread t4 = new Thread(t);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
7.死锁/线程间通信
/*
死锁程序经典案例。面试可以用
*/
class Test implements Runnable
{
private boolean flag;
Test(boolean flag)
{
this.flag = flag;
}
public void run()
{
if(flag)
{
while(true)
{
synchronized(MyLock.locka)
{
System.out.println("if locka");
synchronized(MyLock.lockb)
{
System.out.println("if lockb");
}
}
}
}
else
{
while(true)
{
synchronized(MyLock.lockb)
{
System.out.println("else lockb");
synchronized(MyLock.locka)
{
System.out.println("else locka");
}
}
}
}
}
}
class MyLock
{
static Object locka = new Object();
static Object lockb = new Object();
}
class DeadLockTest
{
public static void main(String[] args)
{
Thread t1= new Thread(new Test(true));
Thread t2= new Thread(new Test(false));
t1.start();
t2.start();
}
}
/*
经典:面试用。
JDK1.5中提供了多线程升级解决方案
将同步synchronized替换成显示的Lock操作
将Object中的wait,notify,notifyAll,替换了condition对象。
该对象可以通过Lock锁进行获取
该示例中,实现了本方只唤醒对方的操作。
*/
class Resource
{
private String name;
private int count = 1;
private boolean flag = false;
private Lock lock = new ReentrantLock();
private Condition condition_pro = lock.newCondition();
private Condition condition_con = lock.newCondition();
public void set(String name)throws InterruptedException
{
lock.lock();
try
{
while(flag)
condition_pro.await();
this.name = name+"--"+count++;
System.out.println(Thread.currentThread().getName()+"...生产者........."+this.name);
flag = true;
condition_con.signal();
}finally
{
lock.unlock();//释放锁的动作一定要执行,放在finally里面
}
}
public void out()throws InterruptedException
{
lock.lock();
try
{
while(!flag)
condition_con.await();
System.out.println(Thread.currentThread().getName()+"...消费者..."+this.name);
flag = false;
condition_pro.signal();
}finally
{
lock.unlock();
}
}
}
class Producer implements Runnable
{
private Resource res;
Producer(Resource res)
{
this.res = res;
}
public void run()
{
while(true)
{
try
{
res.set("+商品+");
}
catch (InterruptedException e)
{
}
}
}
}
class Consumer implements Runnable
{
private Resource res;
Consumer(Resource res)
{
this.res = res;
}
public void run()
{
while(true)
{
try
{
res.out();
}
catch (InterruptedException e)
{
}
}
}
}
/*
线程间通讯:
其实就是多个线程在操作同一个资源
但是操作的动作不同。
*/
class Res
{
private String name;
private String sex;
private boolean flag = false;
public synchronized void set(String name,String sex)
{
this.name = name;
this.sex = sex;
}
public synchronized void out()
{
System.out.println(name+"....."+sex);
}
}
class Input implements Runnable
{
private Res r;
//Object obj = new Object();
Input(Res r)
{
this.r = r;
}
public void run()
{
int x = 0;
while(true)
{
//synchronized(Input.class) 只要在内存中是唯一的对象就行
synchronized(r)
{
if(r.flag)
try{r.wait();}catch(Exception e){}
if(x == 0)
{
r.name = "mike";
r.sex = "man";
}
else
{
r.name = "丽丽";
r.sex = "女";
}
x = (x+1)%2;
r.flag = true;
r.notify();
}
}
}
}
class Output implements Runnable
{
private Res r;
//Object obj = new Object();
Output(Res r)
{
this.r = r;
}
public void run()
{
while(true)
{
//synchronized(Input.class) 只要在内存中是唯一的对象就行
synchronized(r)
{
if(!r.flag)
try{r.wait();}catch(Exception e){}
System.out.println(r.name+"..."+r.sex);
r.flag = false;
r.notify();
}
}
}
}
class InputOutput
{
public static void main(String[] args)
{
Res r = new Res();
Input in = new Input(r);
Output op = new Output(r);
Thread t1 = new Thread(in);
Thread t2 = new Thread(op);
t1.start();
t2.start();
}
}
/*
wait():
nofity():
notifyAll():
都使用在同步中,因为要对持有监视器(锁)的线程操作。
所以要使用在同步中,因为只有同步才具有锁。
为什么这些操作线程的方法要定义在Object类中呢?
因为这些方法在操作同步中线程时,都必须要标识它们所操作线程持有的锁,
只有同一个锁上的被等待线程,可以被同一个锁上的notify唤醒,
不可以对不同锁中的线程进行唤醒。
也就是说,等待和唤醒必须是同一个锁,而锁可以是任意对象,所以
可以被任意对象调用的方法定义在Object类中。
*/