我有一个进程,它会被cron相当频繁地调用,以读取其中包含某些与移动相关的命令的文件.我的进程需要读取和写入此数据文件 - 并将其锁定以防止其他进程在此期间触摸它.用户可以执行完全独立的过程(可能)写入/附加到该相同的数据文件.我希望这两个进程运行良好,并且一次只访问一个文件.
nio FileLock似乎是我需要的(没有编写我自己的信号量类型文件),但是我无法将其锁定以供阅读.我可以锁定并写入正常,但在读取时尝试创建锁定时会出现NonWritableChannelException.甚至可以锁定文件进行阅读吗?看起来像RandomAccessFile更接近我的需要,但我不知道如何实现它.
这是失败的代码:
FileInputStream fin = new FileInputStream(f);
FileLock fl = fin.getChannel().tryLock();
if(fl != null)
{
System.out.println("Locked File");
BufferedReader in = new BufferedReader(new InputStreamReader(fin));
System.out.println(in.readLine());
...
Run Code Online (Sandbox Code Playgroud)
FileLock行抛出异常.
java.nio.channels.NonWritableChannelException
at sun.nio.ch.FileChannelImpl.tryLock(Unknown Source)
at java.nio.channels.FileChannel.tryLock(Unknown Source)
at Mover.run(Mover.java:74)
at java.lang.Thread.run(Unknown Source)
Run Code Online (Sandbox Code Playgroud)
它说,看看JavaDocs
尝试写入最初未打开以进行写入的通道时,抛出未经检查的异常.
但我不一定要写信给它.当我尝试创建FileOutpuStream等用于写入目的时,我很高兴,直到我尝试在同一文件上打开FileInputStream.
目前我正在研究在其中一个例程中处理源目录中的文件的项目.有一个Java进程正在查找指定的目录,并尝试读取和处理文件(如果存在).文件退出大,并由其他第三方进程更新.问题是如何检查文件是否完整写入?我试图使用file.length()但看起来即使写入过程尚未完成它返回实际大小.我觉得解决方案应该依赖于平台.任何帮助,将不胜感激.
更新:这个问题与副本没有什么不同,但它有一个高评级的工作代码片段的答案.
我需要在我的Java应用程序中启动1-3个外部程序,这些程序具有用户定义的路径.我的要求很少:
如果程序已经运行,我不希望程序执行
我不希望任何程序从我的Java应用程序中窃取焦点
我不在乎他们中的任何一个是否未能启动.他们只需要默默地失败.
这是我到目前为止提出的:
ProcessBuilder pb = new ProcessBuilder(userDefinedPath1);
try {
pb.start();
}
catch (Exception e) {
// Something went wrong, just ignore
}
Run Code Online (Sandbox Code Playgroud)
然后我用另外两条路径再重复3次.这开始就像我期望的那样,并且满足我的第三个要求就好了,但是前两个失败了.
做这个的最好方式是什么?
编辑:
我对这些其他应用程序没有任何控制权.他们是第三方.此外,用户可以随时手动启动或停止它们.
我知道可执行文件的确切名称(例如"blah.exe")并且它们将始终相同,但可执行文件的路径不一定如此.
批处理文件包装器在这里是不可行的.
其他应用程序不是 Java应用程序,只是普通的旧Windows可执行文件.
我有一个portlet.当portlet加载时,则在呈现第一个视图之前,在某些情况下需要调用更改数据库中数据的存储库.我不会详细说明为什么这是必要的,关于这是一个设计缺陷的答案是没有用的.我知道这是一个设计缺陷,但我仍然希望找到以下问题的替代解决方案:
这种设置的问题是浏览器发送预加载请求.例如,portlet所在页面的URL是/ test-portlet.现在,当您在地址栏中键入它时,如果您在浏览器历史记录中输入它,则浏览器会在向您建议时向页面发送GET请求.如果在解析第一个GET请求之前按Enter键,则浏览器会发送新的GET请求.这意味着portlet接收2个独立的请求,它们开始并行处理.第一个数据库过程可能正常工作,但考虑到数据库过程的性质,第二个调用通常会给出异常.
从Java应用程序处理上述问题的干净方法是什么?
旁注:我正在使用Spring MVC.
一个可能的控制器的简单示例:
@RequestMapping
public String index( Model model, RenderRequest request ){
String username = dummyRepository.changeSomeData(request.getAttribute("userId"));
model.add("userName", username);
return "view";
}
Run Code Online (Sandbox Code Playgroud)
我会对阻止第一次执行的解决方案感兴趣.例如,某些从控制器重定向到POST的浏览器不会触发.不确定它是否可以实现.
我们的java程序不断地将一些重要数据写入文件.现在我们想要在某些用户手动删除文件(java程序正在编写的文件)时抛出一些异常或在控制台上显示某种错误消息.
我发现java在尝试写入已删除的文件时不会抛出任何异常.
方法I -启动一个新线程,该线程将继续检查文件是否存在,并在删除文件时通知主java程序.这在我们的情况下不起作用,因为我们将有几个java程序将要编写的文件,因此为每个文件启动一个新线程将不具有内存效率.
方法II -每次在写入文件之前检查文件是否存在.这也不是一个好方法,因为检查文件存在是一个更昂贵的操作.
方法III -扩展java.io.FilterWriter(我们用来写入文件)并覆盖write()方法,以便在尝试写入已删除的文件时抛出异常.这似乎是一个很好的解决方案,但我找不到任何地方Java正在消化一些异常(当它试图写入已被删除的文件时),我们可以通过覆盖该方法抛出.
我需要能够用Java模仿'tail -f'.我正在尝试读取一个日志文件,因为它是由另一个进程写的,但是当我打开文件来读取它时,它会锁定文件而另一个进程无法再写入它.任何帮助将不胜感激!
这是我目前使用的代码:
public void read(){
Scanner fp = null;
try{
fp = new Scanner(new FileReader(this.filename));
fp.useDelimiter("\n");
}catch(java.io.FileNotFoundException e){
System.out.println("java.io.FileNotFoundException e");
}
while(true){
if(fp.hasNext()){
this.parse(fp.next());
}
}
}
Run Code Online (Sandbox Code Playgroud) 我正在尝试用Java实现以下操作,我不知道如何:
/*
* write data (Data is defined in my package)
* to a file only if it does not exist, return success
*/
boolean writeData(File f, Data d)
{
FileOutputStream fos = null;
try
{
fos = atomicCreateFile(f);
if (fos != null)
{
/* write data here */
return true;
}
else
{
return false;
}
}
finally
{
fos.close(); // needs to be wrapped in an exception block
}
}
Run Code Online (Sandbox Code Playgroud)
是否存在我可以使用的功能atomicCreateFile()?
编辑:哦,我不确定File.createNewFile()是否足以满足我的需求.如果我调用f.createNewFile()然后在它返回的时间和我打开文件进行写入之间,其他人已经删除了该文件,该怎么办?有没有办法我可以创建文件并打开它来写入+锁定它,一举一动?我需要担心吗?
在我的小型独立Java应用程序中,我想存储信息.
我的要求:
因此,我想使用jaxb将所有信息存储在文件系统中的简单XML文件中.我的示例应用程序看起来像这样(将所有代码复制到一个名为Application.java和编译的文件中,没有其他要求!):
@XmlRootElement
class DataStorage {
String emailAddress;
List<String> familyMembers;
// List<Address> addresses;
}
public class Application {
private static JAXBContext jc;
private static File storageLocation = new File("data.xml");
public static void main(String[] args) throws Exception {
jc = JAXBContext.newInstance(DataStorage.class);
DataStorage dataStorage = load();
// the main application will be executed here
// data manipulation like this:
dataStorage.emailAddress = "me@example.com";
dataStorage.familyMembers.add("Mike");
save(dataStorage);
}
protected static DataStorage load() …Run Code Online (Sandbox Code Playgroud) 可能的重复:
如何使用 java 锁定文件(如果可能)
我有两个进程调用两个修改相同文本文件的 Java 程序。我注意到文本文件的内容缺少数据。我怀疑当一个 java 程序获取到文本文件的写入流时,我认为它会阻止另一个 java 程序修改它(就像当你打开一个文件时,你不能删除那个文件)。除了数据库,有没有办法解决这个问题?(不是说db解决方案不干净或不优雅,只是我们在操作这个文本文件时写了很多代码)
编辑
事实证明,我针对这个问题犯了一个错误。我的文本文件中的数据丢失的原因是,
ProcessA: 继续将数据行添加到文本文件中
ProcessB: 在开始时,将文本字段的所有行加载到一个List. 然后操作该列表的包含。最后,ProcessB将列表写回,替换文本文件的包含。
这在顺序过程中效果很好。但是当一起运行时,如果ProcessA向文件中添加数据,在ProcessB操作期间List,那么当ProcessB写List回时,无论ProcessA添加什么,都会被覆盖。所以我最初的想法是在ProcessB写List回之前,同步文本文件和List. 所以当我写List回时,它将包含所有内容。所以这是我的努力
public void synchronizeFile(){
try {
File file = new File("path/to/file/that/both/A/and/B/write/to");
FileChannel channel = new RandomAccessFile(file, "rw").getChannel();
FileLock lock = channel.lock(); //Lock the file. Block until release the lock
List<PackageLog> tempList = readAllLogs(file);
if(tempList.size() > …Run Code Online (Sandbox Code Playgroud) java ×10
io ×3
filelock ×2
file ×1
file-io ×1
file-locking ×1
file-storage ×1
filesystems ×1
filewriter ×1
java-io ×1
jaxb ×1
pid ×1
portlet ×1
spring ×1
spring-mvc ×1
writer ×1
xml ×1