11

我在 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

4

5 回答 5

6

所以也许我遗漏了一些东西,但我看到上面的代码存在一些问题。您的具体问题可能是由于(如@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);
}
于 2011-08-31T15:27:42.390 回答
6

在 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);

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

于 2012-12-21T19:58:34.910 回答
5

如果这一切都不起作用,请尝试从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();
于 2013-06-20T07:25:39.957 回答
1

适用于某些设备,但不适用于其他设备。不要设计依赖于它工作的解决方案。见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());
}
于 2011-09-16T01:48:30.780 回答
0

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

于 2015-04-14T13:38:04.483 回答