Java對檔案的操作及UDP,TCP

weixin_34146805發表於2018-07-12

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類中。

*/

相關文章