繁体   English   中英

file.lastModified() 永远不是用 file.setLastModified() 设置的

[英]file.lastModified() is never what was set with file.setLastModified()

我在 Nexus One 上的 Android 2.3.4 上设置和读取 Millis 确实有问题。 这是代码:

File fileFolder = new File(Environment.getExternalStorageDirectory(), appName + "/"
    + URLDecoder.decode(folder.getUrl()));
if (fileFolder != null && !fileFolder.exists()) {
  fileFolder.setLastModified(1310198774);
  fileFolder.mkdirs();
  fileFolder.setLastModified(1310198774);
}

if (fileFolder != null && fileFolder.exists()) {
  long l = fileFolder.lastModified();
}

在这个小测试中,我写了 1310198774,但从 lastModified() 返回的结果是 1310199771000。

即使我剪掉后面的“000”,也会有几分钟的差异。

我需要在网络服务和 Android 设备之间同步文件。 lastmodification 毫秒是此服务发送的数据的一部分。 我确实将millis设置为创建/复制的文件和文件夹,以检查文件/文件夹是否需要被覆盖。

一切正常,但从文件系统返回的毫秒与设置的值不同。

我很确定我的代码有问题 - 但我找不到它。

提前谢谢了。 HJW

所以也许我遗漏了一些东西,但我看到上面的代码存在一些问题。 您的具体问题可能是由于(如@JB 所述)Android 问题,但为了后代,我想我会提供一个答案。

首先, File.setLastModified()需要以毫秒为单位的时间。 这是javadocs 你似乎试图在几秒钟内设置它。 所以你的代码应该是这样的:

fileFolder.setLastModified(1310198774000L);

正如 javadocs 中提到的,许多文件系统仅支持上次修改时间的秒粒度。 因此,如果您需要在文件中查看相同的修改时间,那么您应该执行以下操作:

private void changeModificationFile(File file, long time) {
    // round the value down to the nearest second
    file.setLastModified((time / 1000) * 1000);
}

在 Jelly Bean+ 上,情况有所不同(主要是在 Nexus 设备上,以及其他使用新熔丝层进行 /mnt/shell/emulated sdcard 仿真的其他设备):

这是一个 VFS 权限问题,系统调用 utimensat() 由于权限不当(例如所有权)而因 EPERM 而失败。

在平台/系统/核心/sdcard/sdcard.c:

/* root.sdcard 拥有的所有文件 */
attr->uid = 0;
attr->gid = AID_SDCARD_RW;

从 utimensat() 的系统调用手册页:

2. the caller's effective user ID must match the owner of the file; or  
3. the caller must have appropriate privileges.  

To make any change other than setting both timestamps to the current time  
(i.e., times is not NULL, and both tv_nsec fields are not UTIME_NOW and both  
tv_nsec fields are not UTIME_OMIT), either condition 2 or 3 above must apply.  

旧 FAT 通过挂载选项提供了对 iattr->valid 标志的覆盖,以允许将时间戳更改为任何人,FUSE+Android 的 sdcard-FUSE 目前不这样做(因此 'inode_change_ok() 调用失败)并且尝试被 -EPERM 拒绝。 这是FAT的./fs/fat/file.c:

/* Check for setting the inode time. */  
ia_valid = attr->ia_valid;  
if (ia_valid & TIMES_SET_FLAGS) {  
    if (fat_allow_set_time(sbi, inode))  
        attr->ia_valid &= ~TIMES_SET_FLAGS;  
}  

error = inode_change_ok(inode, attr);

我还将此信息添加到此打开的错误中。

如果这一切都不起作用,请尝试从https://code.google.com/p/android/issues/detail?id=18624引用的这个(丑陋的)解决方法:

//As a workaround, this ugly hack will set the last modified date to now:      
RandomAccessFile raf = new RandomAccessFile(file, "rw");
long length = raf.length();
raf.setLength(length + 1);
raf.setLength(length);
raf.close();

适用于某些设备,但不适用于其他设备。 不要设计依赖于它工作的解决方案。 https://code.google.com/p/android/issues/detail?id=18624#c29

这是一个简单的测试,看看它是否有效。

public void testSetLastModified() throws IOException {
    long time = 1316137362000L;
    File file = new File("/mnt/sdcard/foo");
    file.createNewFile();
    file.setLastModified(time);
    assertEquals(time, file.lastModified());
}

如果您只想将目录的日期/时间更改为当前日期/时间(即“现在”),那么您可以在该目录中创建某种临时文件,在其中写入一些内容,然后立即将其删除。 这具有将目录的“lastModified()”日期/时间更改为当前日期/时间的效果。 但是,如果您想将目录日期/时间更改为其他随机值,并且显然不能应用于文件,这将不起作用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM