0

我正在编写一个将数据保存到 CSV 文件的游戏小程序,并获得了一些可以读取和写入同一.csv文件的方法。不知何故,我需要锁定文件,而我的每个方法都有一个打开的写入器流到文件,所以在我关闭写入流之前无法更改文件内容,但我只想允许读取访问。

可能吗?

或者,如果它可以在完全不访问文件的情况下完成,那也很好。

编辑:我的电脑将成为提供在线游戏小程序的服务器,而 csv 文件仅在我的电脑上。要玩本游戏,您必须登录我的网站,并将所有帐户信息(用户名、密码、总赢、总输等)存储到我的计算机(服务器)上的 csv 文件中。所以我有几种方法可以更改文件。因此,我需要在写入文件时将其锁定在每种方法中,如果从理论上讲,将是几个玩家同时玩。

我将信息存储到 csv 文件的原因是我接受了 java 开发人员的教育并且只编程了 4 个月,我们将在几个月内首先了解数据库。

这是一项功课,这就是我制作小程序的原因。唯一将连接到我的计算机(将通过一个简单的 servlet 和网页为小程序提供服务)的用户是我的老师。所以不存在安全威胁。

这是播放器对象的代码:

public class Player {
    private String userName;
    private String passWord;
    private int currentWins;
    private int currentLosses;
    private int totalWins;
    private int totalLosses;
    private boolean isLoggedIn = false;
    private String playerId; 
    public Player(String playerId, String userName, String passWord, int totalWins, int totalLosses) { 
        this.playerId = playerId;
        this.userName = userName;
        this.passWord = passWord;
        this.totalWins = totalWins;
        this.totalLosses = totalLosses;
        this.currentWins = 0;
        this.currentLosses = 0;
        }
    public Player(String userName, String passWord, int totalWins, int totalLosses) {
        this.userName = userName;
        this.passWord = passWord;
        this.totalWins = totalWins;
        this.totalLosses = totalLosses;
        this.currentWins = 0;
        this.currentLosses = 0;
        this.playerId = UUID.randomUUID().toString();
    }
    public void incrementWins()
    {
        currentWins++;
        totalWins++;
    }
    public void incrementLosses()
    {
        currentLosses++;
        totalLosses++;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public String getPassword() {
        return passWord;
    }
    public void setPassword(String passWord) {
        this.passWord = passWord;
    }
    public boolean isLoggedIn() {
        return isLoggedIn;
    }
    public void setLoggedIn(boolean isLoggedIn) {
        this.isLoggedIn = isLoggedIn;
    }
    public int getTotalWins()
    {
        return this.totalWins;
    }
    public void setTotalWins(int totalWins)
    {
        this.totalWins = totalWins;
    }
    public int getTotalLoss()
    {
        return this.totalLosses;
    }
    public void setTotalLoss(int totalLoss)
    {
        this.totalLosses = totalLoss;
    }
    public int getCurrentWins()
    {
        return this.currentWins;
    }
    public void setCurrentWins(int currentWins)
    {
        this.currentWins = currentWins;
    }
    public int getCurrentLoss()
    {
        return this.currentLosses;
    }
    public void setCurrentLoss(int currentLosses)
    {
        this.currentLosses = currentLosses;
    }
    public String getPlayerId() {
        return playerId;
    }
    public void setPlayerId(UUID playerId) {
        this.playerId = playerId.toString();
    }   
}

这里播放器管理器代码:

public class PlayerManager {
    private final File file = new File("Players.csv");
    public PlayerManager() throws IOException
    {
        if (!file.exists())
            file.createNewFile();
    }

    public Player getPlayer(String playerId) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));

        String line;

        while((line = reader.readLine()) != null) {
            if(line.equalsIgnoreCase("PlayerID;Username;Password;Total Wins;Total Losses"))
                continue;

            String[] playerInfo = line.split(";");
            String existingPlayerID = playerInfo[0];
            String userName = playerInfo[1];
            String password = playerInfo[2];
            int totalWins = Integer.parseInt(playerInfo[3]);
            int totalLoss = Integer.parseInt(playerInfo[4]);

            if(existingPlayerID.equals(playerId)) {
                reader.close();
                return new Player(existingPlayerID,userName, password, totalWins, totalLoss);
            }
        }

        reader.close();
        return null;
    }
    public ArrayList<Player> getAllPlayers() throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "utf-8"));
        ArrayList<Player> players = new ArrayList<Player>();
        String line;
        while((line = reader.readLine()) != null)
        {
            if(line.equalsIgnoreCase("PlayerID;Username;Password;Total Wins;Total Losses"))
                continue;
            String[] playerInfo = line.split(";");
            String playerID = playerInfo[0];
            String userName = playerInfo[1];
            String password = playerInfo[2];
            int totalWins = Integer.parseInt(playerInfo[3]);
            int totalLoss = Integer.parseInt(playerInfo[4]);
            players.add(new Player(playerID,userName, password, totalWins, totalLoss));
        }
        reader.close();
        return players;
    }
    public void savePlayer(Player player) throws IOException {
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file, true), "utf-8"));
        if(file.length() == 0) {
            writer.write("PlayerID;Username;Password;Total Wins;Total Losses");
            writer.newLine();
            writer.flush();
        }
        if(playerExists(player)) {
            writer.close();
            updatePlayer(player);
            return;
        }
        writer.write(player.getPlayerId() + ";" + player.getUserName() + ";" + player.getPassword() + ";" + 
                player.getTotalWins() + ";" + player.getTotalLoss());
        writer.newLine();
        writer.flush();
        writer.close();
    }
    public Player loginPlayer(String userName, String passWord) throws IOException {

        for(Player p : getAllPlayers()) {
            if(p.isLoggedIn())
                return p;

            if(p.getUserName().equals(userName) && p.getPassword().equals(passWord)) {
                p.setLoggedIn(true); 
                return p;
            }
        }
        return null;
    }
    private void updatePlayer(Player player) {

        try
        {
            ArrayList<Player> players = getAllPlayers();
            for(Player p : players) {
                if(p.getPlayerId().equals(player.getPlayerId())) {
                    p.setUserName(player.getUserName());
                    p.setPassword(player.getPassword());
                    p.setCurrentWins(player.getCurrentWins());
                    p.setCurrentLoss(player.getCurrentLoss());
                    p.setLoggedIn(player.isLoggedIn());
                    p.setTotalWins(player.getTotalWins());
                    p.setTotalLoss(player.getTotalLoss());
                    break;
                }
            }
            File tempFile = new File("Players.csv.bak");
            if (!tempFile.exists())
                tempFile.createNewFile();
            else
            {
                tempFile.delete();
                tempFile.createNewFile();
            }
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(tempFile), "utf-8"));

            if(tempFile.length() == 0) {
                writer.write("PlayerID;Username;Password;Total Wins;Total Losses");
                writer.newLine();
                writer.flush();
            }
            for(Player p : players) {
                writer.write(p.getPlayerId() + ";" + p.getUserName() + ";" + p.getPassword() + ";" + 
                        p.getTotalWins() + ";" + p.getTotalLoss());
                writer.newLine();
            }
            writer.flush();
            writer.close();
            this.file.delete();
            tempFile.renameTo(this.file);
        }
        catch(Exception ex)
        {
        }
    }
    private boolean playerExists(Player player) throws IOException {
        Player p = getPlayer(player.getPlayerId());

        if(p != null && p.getPlayerId().equals(player.getPlayerId()))
            return true;
        return false;
    }
} 

这是 servlet(尚未完成):

public class TickTackToeServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    private boolean newUser = true;

    public String getLoginForm() throws IOException {
        File loginForm = new File("login.html");
        BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(loginForm)));
        StringBuilder str = new StringBuilder();

        String line;
        while((line = reader.readLine()) != null) {
            str.append(line);
        }

        reader.close();
        return str.toString();
    }

    public String displayGamePage() {
        return null;
    }

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        response.setContentType("text/html; charset=utf-8");
        response.setStatus(HttpServletResponse.SC_OK);
        Writer writer = response.getWriter();

        String loginForm = getLoginForm();

        writer.write(loginForm);
    }

    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        response.setContentType("text/html; charset=utf-8");
        Writer writer = response.getWriter();

        String userName = request.getParameter("username");
        String passWord = request.getParameter("password");

        if(userName == null || passWord == null) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            writer.write("<h1>You forgot to enter username/password. Please refresh to try again.</h1>");
            writer.write(getLoginForm());
            return;
        }

        PlayerManager playerManager = new PlayerManager();
        playerManager.loginPlayer(userName, passWord);

        Player player = new Player(userName, passWord, 0 , 0);
        if(!player.isLoggedIn()) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            writer.write("<h1>Bad username or password. Please refresh to try again.</h1>");
            return;
        }

        HttpSession session = request.getSession(true);

        if(session.getAttribute(userName) == null || session.getAttribute(passWord) == null) {
            session.setAttribute("username", userName);
            session.setAttribute("password", passWord);
        }

        response.setStatus(HttpServletResponse.SC_OK);
        response.sendRedirect(request.getParameter("url"));

    }

    public static void main(String... args) throws Exception {
        ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
        context.addServlet(TickTackToeServlet.class, "/");

        Server server = new Server(8080);
        server.setHandler(context);
        server.start();
        server.join();
    }

}

这是小程序(尚未完成):

public class TickTackToeApplet extends JApplet implements ActionListener {
    private static final long serialVersionUID = 1L;
    private ArrayList<JButton> buttons = new ArrayList<JButton>();

    private JPanel panel = new JPanel();
    private Game game;
    private Player player1;
    private Player player2;
    private int numberOfPlacedOutChars = 0;

    public TickTackToeApplet() {}


    public TickTackToeApplet(int gameBoardSize, Player player1, Player player2) {
        createGUI(gameBoardSize);

        game = new Game(gameBoardSize);
        this.player1 = player1;
        this.player2 = player2;

        if(!player1.isLoggedIn() && !player2.isLoggedIn()) {
            try {
                PlayerManager playerManager = new PlayerManager();

                playerManager.loginPlayer(player1.getUserName(), player1.getPassword());
                playerManager.loginPlayer(player2.getUserName(), player1.getPassword());
            } catch (IllegalArgumentException e) {
                JOptionPane.showMessageDialog(this, "Couldn't login player, please enter correct username & password!");
            } catch (IOException e) {
                JOptionPane.showMessageDialog(this, "Server error...");
                e.printStackTrace();
            }
        }
    }

    //  public void init() {
    //      new TickTackToeApplet(4, "Henrik", "temp123");
    //  }

    public void CreateButtons(int gameBoardSize)
    {
        for(int x=0; x<gameBoardSize; x++)
        {
            for(int y=0; y<gameBoardSize; y++)
            {
                JButton btn = new JButton("");
                btn.setFont(new Font("Tahoma", Font.PLAIN, 32));
                btn.setName(x + ";" + y);
                btn.addActionListener(this);
                buttons.add(btn);
            }
        }
    }

    public void PlaceOutButtons()
    {
        for(JButton btn : buttons)
            panel.add(btn);
    }

    public void createGUI(int gameBoardSize) {

        panel.setSize(gameBoardSize*25, gameBoardSize*25);
        panel.setBackground(Color.BLACK);
        getContentPane().add(panel, BorderLayout.CENTER);
        panel.setLayout(new GridLayout(gameBoardSize, gameBoardSize));

        CreateButtons(gameBoardSize);
        PlaceOutButtons();
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        JButton buttonClicked = (JButton)e.getSource();
        String coordinates = buttonClicked.getName();
        String[] strArr = coordinates.split(";");
        int x = Integer.parseInt(strArr[0]);
        int y = Integer.parseInt(strArr[1]);

        if (numberOfPlacedOutChars % 2 == 0) {
            game.placeChar('X', x, y);
            buttonClicked.setText("X");
            buttonClicked.setEnabled(false);
        }
        else {
            game.placeChar('O', x, y);
            buttonClicked.setText("O");
            buttonClicked.setEnabled(false);
        }

        numberOfPlacedOutChars++;

        boolean win = game.checkWin();

        if(win == true) {
            player1.incrementWins();
            try {
                PlayerManager playerManager = new PlayerManager();
                playerManager.savePlayer(player1);
            } catch (IllegalArgumentException | IOException e1) {
                JOptionPane.showMessageDialog(this, "Couldn't update player info!");
            } 

            for(JButton btn : buttons) {
                btn.setEnabled(false);
            }

            int choice = JOptionPane.showConfirmDialog(this, "Winner is: " + player1.getUserName() + ", play again?", "WE GOT A WINNER", JOptionPane.YES_NO_OPTION);

            if(choice == 0) {
                for(JButton btn : buttons) {
                    btn.setEnabled(true);
                    btn.setText("");
                }
            }
        }
    }

}
4

1 回答 1

2

使用 Java.NIO,您可以使用一个名为FileLock的类来做到这一点。这是取自一篇关于 JavaBeat的文章的示例:

import java.io.*;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;

public class FileLockTest {
  public static void main(String[] args) throws Exception {
    RandomAccessFile file = null;
    FileLock fileLock = null;
    try {
      file = new RandomAccessFile("FileToBeLocked", "rw");
      FileChannel fileChannel = file.getChannel();

      fileLock = fileChannel.tryLock();
      if (fileLock != null){
        System.out.println("File is locked");
        accessTheLockedFile();
      }
    } finally {
      if (fileLock != null) {
        fileLock.release();
      }
    }
  }

  static void accessTheLockedFile() {
    try {
      FileInputStream input = new FileInputStream("FileToBeLocked");
      int data = input.read();
      System.out.println(data);
    } catch (Exception exception) {
      exception.printStackTrace();
    }
  }
}

因为这涉及到文件系统,所以您需要一个 .policy 文件,并且您需要对小程序进行签名。尽管您应该阅读以下内容,但该政策应该有效:

grant {
  permission java.io.FilePermission "<<ALL FILES>>","write";
};
于 2013-01-04T00:25:57.350 回答