免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: Herowinter
打印 上一主题 下一主题

[函数] 要写一个file_copy函数 [复制链接]

论坛徽章:
769
金牛座
日期:2014-02-26 17:49:58水瓶座
日期:2014-02-26 18:10:15白羊座
日期:2014-04-15 19:29:52寅虎
日期:2014-04-17 19:43:21酉鸡
日期:2014-04-19 21:24:10子鼠
日期:2014-04-22 13:55:24卯兔
日期:2014-04-22 14:20:58亥猪
日期:2014-04-22 16:13:09狮子座
日期:2014-05-05 22:31:17摩羯座
日期:2014-05-06 10:32:53处女座
日期:2014-05-12 09:23:11子鼠
日期:2014-05-21 18:21:27
21 [报告]
发表于 2015-01-28 21:12 |只看该作者
回复 20# cobras


哦,太感谢了,boost已经被老板否了,说那个库太大。
剩下的办法好像只有正则或自己解析,正则是C++11的,
老板应该也不会同意,只能自己处理了,正好可以参考一下
您的代码。

论坛徽章:
17
处女座
日期:2013-08-27 09:59:352015亚冠之柏太阳神
日期:2015-07-30 10:16:402015亚冠之萨济拖拉机
日期:2015-07-29 18:58:182015年亚洲杯之巴勒斯坦
日期:2015-03-06 17:38:17摩羯座
日期:2014-12-11 21:31:34戌狗
日期:2014-07-20 20:57:32子鼠
日期:2014-05-15 16:25:21亥猪
日期:2014-02-11 17:32:05丑牛
日期:2014-01-20 15:45:51丑牛
日期:2013-10-22 11:12:56双子座
日期:2013-10-18 16:28:17白羊座
日期:2013-10-18 10:50:45
22 [报告]
发表于 2015-01-29 20:53 |只看该作者
本帖最后由 myworkstation 于 2015-01-29 21:03 编辑

回复 17# Herowinter


    boost filesystem 不支持wildcards,wildcards实际上是shell进行解析的(Filename Expansion),自己处理wildcards的话可以看看这几个函数(属于POSIX标准的一部分):glob, glob_b, globfree,fnmatch,wordexp

论坛徽章:
769
金牛座
日期:2014-02-26 17:49:58水瓶座
日期:2014-02-26 18:10:15白羊座
日期:2014-04-15 19:29:52寅虎
日期:2014-04-17 19:43:21酉鸡
日期:2014-04-19 21:24:10子鼠
日期:2014-04-22 13:55:24卯兔
日期:2014-04-22 14:20:58亥猪
日期:2014-04-22 16:13:09狮子座
日期:2014-05-05 22:31:17摩羯座
日期:2014-05-06 10:32:53处女座
日期:2014-05-12 09:23:11子鼠
日期:2014-05-21 18:21:27
23 [报告]
发表于 2015-01-29 21:29 |只看该作者
回复 22# myworkstation


哦,非常感谢大神帮助,看看能不能说服老板用正则,这样好像代码简单点,
带通配符文件名中的  
    .=>\.
    *=>.*
    ? =>.
这样转换的正则应该和本来的通配符等价的。然后再写个函数递归遍历目录下
的所有文件目录,Windows有个FindFirstFile, POSIX有个opendir。再判断
一下文件名是不是match正则应该就可以了。

我现在的方案这样的,老板不认同,只能去啃您说的那几个函数了。

论坛徽章:
44
15-16赛季CBA联赛之浙江
日期:2021-10-11 02:03:59程序设计版块每日发帖之星
日期:2016-07-02 06:20:0015-16赛季CBA联赛之新疆
日期:2016-04-25 10:55:452016科比退役纪念章
日期:2016-04-23 00:51:2315-16赛季CBA联赛之山东
日期:2016-04-17 12:00:2815-16赛季CBA联赛之福建
日期:2016-04-12 15:21:2915-16赛季CBA联赛之辽宁
日期:2016-03-24 21:38:2715-16赛季CBA联赛之福建
日期:2016-03-18 12:13:4015-16赛季CBA联赛之佛山
日期:2016-02-05 00:55:2015-16赛季CBA联赛之佛山
日期:2016-02-04 21:11:3615-16赛季CBA联赛之天津
日期:2016-11-02 00:33:1215-16赛季CBA联赛之浙江
日期:2017-01-13 01:31:49
24 [报告]
发表于 2015-01-30 00:42 |只看该作者
回复 22# myworkstation

Windows里wildcard解析是文件系统驱动做的(不知道是哪个脑残设计的…………)

论坛徽章:
2
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:56:11
25 [报告]
发表于 2015-01-30 11:52 |只看该作者
发个windows文件通配例子。
  1. #include <ctype.h>
  2. #include <stdio.h>
  3. #include <windows.h>

  4. #define PATH_SPLITTER '\\'

  5. #define LENGTH(a) (sizeof(a)/sizeof((a)[0]))

  6. struct file_node
  7. {
  8.         long size;
  9. };

  10. int nstr_chr(const char *s, int off, int lmt, int c)
  11. {
  12.         for (; off < lmt; ++off) {
  13.                 if (s[off] == c) {
  14.                         return off;
  15.                 }
  16.         }
  17.         return -1;
  18. }

  19. int nstr_rchr(const char *s, int off, int lmt, int c)
  20. {
  21.         for (; off < lmt; --lmt) {
  22.                 if (s[lmt - 1] == c) {
  23.                         return lmt;
  24.                 }
  25.         }
  26.         return -1;
  27. }

  28. int nstr_npbrk(const char *s, int off, int lmt, const char *charset, int charset_len)
  29. {
  30.         for (; off < lmt; ++off) {
  31.                 if (nstr_chr(charset, 0, charset_len, s[off]) != -1) {
  32.                         return off;
  33.                 }
  34.         }
  35.         return -1;
  36. }

  37. int nstr_lmt(const char *s, int lmt)
  38. {
  39.         int off;

  40.         off = nstr_chr(s, 0, lmt, '\0');
  41.         if (off == -1) {
  42.                 off = lmt;
  43.         }
  44.         return off;
  45. }

  46. int nstr_nmatch(const char *s, int off, int lmt, const char *rules, int rules_len)
  47. {
  48.         int rules_off;
  49.         int rules_lmt;
  50.         int rules_next;

  51.         for (rules_off = 0; rules_off < rules_len; rules_off = rules_next) {
  52.                 rules_lmt = nstr_npbrk(rules, rules_off, rules_len, "*?", 2);
  53.                 if (rules_lmt == -1) {
  54.                         rules_next = rules_len;
  55.                         rules_lmt = rules_len;
  56.                 }else {
  57.                         rules_next = rules_lmt + 1;
  58.                 }
  59.                 if (rules_off < rules_lmt) {
  60.                         if (off + rules_lmt - rules_off <= lmt) {
  61.                                 if (strncmp(s + off, rules + rules_off, rules_lmt - rules_off) == 0) {
  62.                                         off += rules_lmt - rules_off;
  63.                                 }else {
  64.                                         return 0;
  65.                                 }
  66.                         }else {
  67.                                 return 0;
  68.                         }
  69.                 }
  70.                 if (rules_lmt < rules_len) {
  71.                         if (rules[rules_lmt] == '?') {
  72.                                 if (off + 1 <= lmt) {
  73.                                         ++off;
  74.                                 }else {
  75.                                         return 0;
  76.                                 }
  77.                         }else { /* '*' */
  78.                                 for(; off < lmt; ++off) {
  79.                                         if (nstr_nmatch(s, off, lmt, rules + rules_next, rules_len - rules_next)) {
  80.                                                 return 1;
  81.                                         }
  82.                                 }
  83.                                 return off == lmt && rules_next == rules_len;
  84.                         }
  85.                 }
  86.         }
  87.         return off == lmt ? 1 : 0;
  88. }

  89. int nstr_nmatch_more(const char *s, int off, int lmt, const char *rules, int rules_len)
  90. {
  91.         int rules_off;
  92.         int rules_lmt;
  93.         int rules_next;

  94.         for (rules_off = 0; rules_off < rules_len; rules_off = rules_next) {
  95.                 rules_lmt = nstr_chr(rules, rules_off, rules_len, ';');
  96.                 if (rules_lmt == -1) {
  97.                         rules_lmt = rules_len;
  98.                         rules_next = rules_len;
  99.                 }else {
  100.                         rules_next = rules_lmt + 1;
  101.                 }
  102.                 if (rules_off < rules_lmt) {
  103.                         if (nstr_nmatch(s, off, lmt, rules + rules_off, rules_lmt - rules_off)) {
  104.                                 return 1;
  105.                         }
  106.                 }
  107.         }
  108.         return 0;
  109. }

  110. int get_path_directory_off(const char *s, int off)
  111. {
  112.         if (off >= 0) {
  113.                 if (off >= 2 && s[off - 1] == ':' && isalpha(s[off - 2])) {
  114.                         return 2;
  115.                 }
  116.                 return 0;
  117.         }
  118.         return -1;
  119. }

  120. int get_path_filename_off(const char *s, int off)
  121. {
  122.         int dir_off;
  123.         int name_off;

  124.         if (off >= 0) {
  125.                 dir_off = get_path_directory_off(s, off);
  126.                 name_off = nstr_rchr(s, dir_off, off, PATH_SPLITTER);
  127.                 if (name_off == -1) {
  128.                         name_off = dir_off;
  129.                 }
  130.                 return name_off;
  131.         }
  132.         return -1;
  133. }

  134. /* enum_dir
  135. *
  136. * RETURN
  137. *
  138. *      0; SUCCESS
  139. *     -1; ERROR: buffer overflow
  140. *     -2; ERROR: directory not found
  141. *     -3; ERROR: file too large
  142. *     -4; ERROR: invalid call back function
  143. *      #; ERROR: enum_func defined error
  144. */

  145. int enum_dir(char *s, int off, int lmt, struct file_node *node, int skip_error, int (*enum_func)(char *s, int off, int lmt, void *data), void *data)
  146. {
  147.         WIN32_FIND_DATA find_data;
  148.         HANDLE hFind;
  149.         int retval;
  150.         int name_off;
  151.         int name_len;

  152.         retval = 0;
  153.         if (off >= 0 && off < lmt) {
  154.                 name_off = get_path_filename_off(s, off);
  155.         }else {
  156.                 retval = -1; /* ERROR: buffer overflow */
  157.         }
  158.         if (retval == 0) {
  159.                 if (name_off == off) {
  160.                         if (name_off + 3 <= lmt) {
  161.                                 strncpy(s + name_off, "*.*", 3);
  162.                                 off = name_off + 3;
  163.                         }else {
  164.                                 retval = -1; /* ERROR: buffer overflow */
  165.                         }
  166.                 }
  167.         }
  168.         if (retval == 0) {
  169.                 if (off + 1 <= lmt) {
  170.                         s[off] = '\0';
  171.                 }else {
  172.                         retval = -1; /* ERROR: buffer overflow */
  173.                 }
  174.         }
  175.         if (retval == 0) {
  176.                 hFind = FindFirstFile(s, &find_data);
  177.                 if (hFind != INVALID_HANDLE_VALUE) {
  178.                         do {
  179.                                 if (strcmp(find_data.cFileName, ".") != 0 && strcmp(find_data.cFileName, "..") != 0) {
  180.                                         name_len = nstr_lmt(find_data.cFileName, LENGTH(find_data.cFileName));
  181.                                         if (name_off + name_len <= lmt) {
  182.                                                 strncpy(s + name_off, find_data.cFileName, name_len);
  183.                                                 off = name_off + name_len;
  184.                                         }else {
  185.                                                 retval = -1; /* ERROR: buffer overflow */
  186.                                         }
  187.                                         if (retval == 0) {
  188.                                                 if (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  189.                                                         if (off + 1 <= lmt) {
  190.                                                                 s[off] = PATH_SPLITTER;
  191.                                                                 ++off;
  192.                                                         }else {
  193.                                                                 retval = -1; /* ERROR: buffer overflow */
  194.                                                         }
  195.                                                 }
  196.                                         }
  197.                                         if (retval == 0) {
  198.                                                 if (off + 1 <= lmt) {
  199.                                                         s[off] = '\0';
  200.                                                 }else {
  201.                                                         retval = -1; /* ERROR: buffer overflow */
  202.                                                 }
  203.                                         }
  204.                                         if (retval == 0) {
  205.                                                 if (find_data.nFileSizeHigh == 0) {
  206.                                                         node->size = find_data.nFileSizeLow;
  207.                                                 }else {
  208.                                                         retval = -3; /* ERROR: file size too large */
  209.                                                 }
  210.                                         }
  211.                                         if (retval == 0) {
  212.                                                 if (enum_func != NULL) {
  213.                                                         retval = (*enum_func)(s, off, lmt, data);
  214.                                                 }else {
  215.                                                         retval = -4; /* ERROR: invalid call back function */
  216.                                                 }
  217.                                         }
  218.                                         if (skip_error) {
  219.                                                 retval = 0;
  220.                                         }
  221.                                 }
  222.                         }while (retval == 0 && FindNextFile(hFind, &find_data));
  223.                         FindClose(hFind);
  224.                 }else {
  225.                         retval = -2; /* ERROR: directory not found */
  226.                 }
  227.         }
  228.         return retval;
  229. }

  230. struct find_param
  231. {
  232.         char filter[256];
  233.         int filter_len;
  234.         struct file_node node;
  235.         int total_find;
  236.         int skip_error;
  237. };

  238. int find_func(char *s, int off, int lmt, struct find_param *param)
  239. {
  240.         int name_off;

  241.         name_off = get_path_filename_off(s, off);
  242.         if (name_off == off) {
  243.                 return enum_dir(s, off, lmt, &param->node, param->skip_error, find_func, param);
  244.         }else {
  245.                 if (nstr_nmatch_more(s, name_off, off, param->filter, param->filter_len)) {
  246.                         printf("%s %d\n", s, param->node.size);
  247.                         ++param->total_find;
  248.                 }
  249.                 return 0;
  250.         }
  251. }

  252. int main(void)
  253. {
  254.         char buf[512];
  255.         struct find_param param;
  256.         int retval;

  257.         strcpy(buf, "c:\\");
  258.         strcpy(param.filter, "read*.txt;*.exe");
  259.         param.filter_len = 15;
  260.         param.total_find = 0;
  261.         param.skip_error = 1;
  262.         retval = enum_dir(buf, 3, 512, &param.node, param.skip_error, find_func, &param);
  263.         printf("TOTAL FIND %d file(s)\n", param.total_find);
  264.         if (retval) {
  265.                 printf("ERROR %d\n", retval);
  266.         }
  267.         return retval;
  268. }
复制代码

论坛徽章:
769
金牛座
日期:2014-02-26 17:49:58水瓶座
日期:2014-02-26 18:10:15白羊座
日期:2014-04-15 19:29:52寅虎
日期:2014-04-17 19:43:21酉鸡
日期:2014-04-19 21:24:10子鼠
日期:2014-04-22 13:55:24卯兔
日期:2014-04-22 14:20:58亥猪
日期:2014-04-22 16:13:09狮子座
日期:2014-05-05 22:31:17摩羯座
日期:2014-05-06 10:32:53处女座
日期:2014-05-12 09:23:11子鼠
日期:2014-05-21 18:21:27
26 [报告]
发表于 2015-01-30 20:56 |只看该作者
回复 25# cobras

多谢多谢,真是羡慕大神们,代码总是信手拈来,
而我每次写个新功能,都要上网找参考才能写。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
27 [报告]
发表于 2015-02-09 22:23 |只看该作者
回复 26# Herowinter


新标准里(http://www.open-std.org/jtc1/sc2 ... ers/2013/n3505.html)很快就有了,别折腾新的了 暂时先用 std:experimental:filesystem::copy_file 顶着

论坛徽章:
769
金牛座
日期:2014-02-26 17:49:58水瓶座
日期:2014-02-26 18:10:15白羊座
日期:2014-04-15 19:29:52寅虎
日期:2014-04-17 19:43:21酉鸡
日期:2014-04-19 21:24:10子鼠
日期:2014-04-22 13:55:24卯兔
日期:2014-04-22 14:20:58亥猪
日期:2014-04-22 16:13:09狮子座
日期:2014-05-05 22:31:17摩羯座
日期:2014-05-06 10:32:53处女座
日期:2014-05-12 09:23:11子鼠
日期:2014-05-21 18:21:27
28 [报告]
发表于 2015-02-11 20:29 |只看该作者
回复 27# lost_templar

多谢提供参考信息,非常好的proposal,真是期待。
但我这个是公司产品的一个小功能,马上要实现好,
等不及这个了。

   

论坛徽章:
769
金牛座
日期:2014-02-26 17:49:58水瓶座
日期:2014-02-26 18:10:15白羊座
日期:2014-04-15 19:29:52寅虎
日期:2014-04-17 19:43:21酉鸡
日期:2014-04-19 21:24:10子鼠
日期:2014-04-22 13:55:24卯兔
日期:2014-04-22 14:20:58亥猪
日期:2014-04-22 16:13:09狮子座
日期:2014-05-05 22:31:17摩羯座
日期:2014-05-06 10:32:53处女座
日期:2014-05-12 09:23:11子鼠
日期:2014-05-21 18:21:27
29 [报告]
发表于 2015-02-13 14:23 |只看该作者
本帖最后由 Herowinter 于 2015-02-13 14:49 编辑

@windoze@myworkstation@cobras
众位大神, 在自己实现file_copy的各种代码里发现一个很要命的bug,
假设我当前目录from, 下面有一个symbol link  
from.lnk -> .
然后我 file_copy("f1", "from.lnk/f1");
source和target其实是同一个文件,这样源文件内容就丢失了.

就算没有link 像"/test/from/f1" 和"/test//from///f1"  这2个不同的字符串
其实表示的也是相同的文件, 请问怎么做pre check, 发现传入的两个字符串
表示的其实是同一个文件.

而strace cp可以发现是同一个文件.
write(2, "`f1' and `../from.lnk/f1' are th"..., 43`f1' and `../from.lnk/f1' are the same file) = 43

论坛徽章:
6
2015年辞旧岁徽章
日期:2015-03-05 16:13:092015年迎新春徽章
日期:2015-03-05 16:13:092015小元宵徽章
日期:2015-03-06 15:58:1815-16赛季CBA联赛之浙江
日期:2016-11-05 14:38:4115-16赛季CBA联赛之新疆
日期:2016-11-11 18:38:06
30 [报告]
发表于 2015-02-13 16:39 |只看该作者
复制前比较下两个文件的设备号与I节点号
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP