Redian新闻
>
如何编写 C 程序在 Linux 上创建音乐播放列表 | Linux 中国

如何编写 C 程序在 Linux 上创建音乐播放列表 | Linux 中国

科技
 
导读:使用我在 Linux 上制作的这个 C 程序在旅途中聆听你喜爱的歌曲。                   
本文字数:5474,阅读时长大约:6分钟

使用我在 Linux 上制作的这个 C 程序在旅途中聆听你喜爱的歌曲。

我最近在 Linux 中编写了一个 C 程序,从我广泛的 MP3 库中创建一个较小的随机 MP3 文件选集。该程序会遍历一个包含我的 MP3 库的目录,然后创建一个包含随机的、较小的歌曲选集的目录。然后我将这些 MP3 文件复制到我的智能手机上,以便随时随地收听。

瑞典是一个人口稀少的国家,有许多农村地区没有完整的手机覆盖。这就是在智能手机上拥有 MP3 文件的原因之一。另一个原因是我并不总是有钱购买流媒体服务,所以我喜欢拥有自己喜欢的歌曲的副本。

你可以从它的 Git 仓库🔗 github.com 下载我的应用。我专门为 Linux 编写了它,部分原因是在 Linux 上很容易找到经过良好测试的文件 I/O 例程。多年前,我尝试使用专有的 C 库在 Windows 上编写相同的程序,但在尝试文件复制时遇到了困难。Linux 使用户可以轻松直接地访问文件系统。

本着开源的精神,我没费多少力气就找到了 Linux 的文件 I/O 代码来激发我的灵感。我还发现了一些启发了我的分配内存的代码。我编写了随机数生成的代码。

该程序的工作方式如下所述:

1. 询问源目录和目标目录。
2. 询问存放 MP3 文件的目录下的文件个数。
3. 搜索你希望复制的收藏的百分比(从 1.0% 到 88.0%)。如果你有 1000 个文件的集合,并希望从你的集合中复制 125 个文件而不是 120 个文件,你也可以输入 12.5% 之类的数字。我将上限设置为 88%,因为复制超过 88% 的库将基本生成与你的基础库相似的库。当然,代码是开源的,因此你可以根据自己的喜好自由修改。
4. 使用指针和 malloc 分配内存。一些操作需要内存,包括代表音乐收藏中文件的字符串列表。还有一个列表来保存随机生成的数字。
5. 生成所有文件范围内的随机数列表(例如,如果集合有 1000 个文件,则为 1 到 1000)。
6. 复制文件。

其中一些部分比其他部分更简单,但代码只有大约 100 行:

  1. #include <dirent.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <sys/types.h> /* include necessary header files */
  5. #include <fcntl.h>
  6. #include <stdlib.h>
  7. #include <unistd.h>
  8. #include <time.h>
  9. #define BUF_SIZE 4096 /* use buffer of 4096 bytes */
  10. #define OUTPUT_MODE 0700 /*protect output file */
  11. #define MAX_STR_LEN 256
  12. int main(void) {
  13. DIR *d;
  14. struct dirent *dir;
  15. char strTemp[256], srcFile[256],
  16. dstFile[256], srcDir[256], dstDir[256];
  17. char **ptrFileLst;
  18. char buffer[BUF_SIZE];
  19. int nrOfStrs=-1, srcFileDesc,
  20. dstFileDesc, readByteCount,
  21. writeByteCount, numFiles;
  22. int indPtrFileAcc, q;
  23. float nrFilesCopy;
  24. // vars for generatingRandNumList
  25. int i, k, curRanNum, curLstInd,
  26. numFound, numsToGen, largNumRange;
  27. int *numLst;
  28. float procFilesCopy;
  29. printf("Enter name of source Directory\n");
  30. scanf("%s", srcDir);
  31. printf("Enter name of destionation Directory\n");
  32. scanf("%s", dstDir);
  33. printf("How many files does the directory with mp3 files contain?\n");
  34. scanf("%d", &numFiles);
  35. printf("What percent of the files do you wish to make a random selection of\n");
  36. printf("enter a number between 1 and 88\n");
  37. scanf("%f", &procFilesCopy);
  38. // allocate memory for filesList, list of random numbers
  39. ptrFileLst= (char**) malloc(numFiles * sizeof(char*));
  40. for (i = 0; i < numFiles; i++) {
  41. ptrFileLst[i] = (char*)malloc(MAX_STR_LEN * sizeof(char));
  42. }
  43. largNumRange = numFiles;
  44. nrFilesCopy = (procFilesCopy / 100) * numFiles;
  45. numsToGen = (int)((procFilesCopy / 100) * numFiles);
  46. printf("nrFilesCopy=%f", nrFilesCopy);
  47. printf("NumsToGen=%d", numsToGen);
  48. numLst = malloc(numsToGen * sizeof(int));
  49. srand(time(0));
  50. numLst[0] = rand() % largNumRange + 1;
  51. numFound=0;
  52. do {
  53. curRanNum = (int)rand() % largNumRange + 1;
  54. if (numLst[0] == curRanNum) {
  55. numFound=1;
  56. }
  57. } while(numFound == 1);
  58. numLst[1] = curRanNum;
  59. getchar();
  60. curLstInd = 1;
  61. i = 0;
  62. while(1) {
  63. do {
  64. numFound = 0;
  65. curRanNum = (int)rand() % largNumRange + 1;
  66. for (int k = 0; k <= curLstInd; k++){
  67. if (numLst[k] == curRanNum)
  68. numFound = 1;
  69. }
  70. } while(numFound == 1);
  71. numLst[curLstInd+1] = curRanNum;
  72. curLstInd++;
  73. i++;
  74. // numsToGen=Total numbers to generate minus two
  75. // already generated by the code above this loop
  76. if (i == (numsToGen-2))
  77. break;
  78. }
  79. d = opendir(srcDir);
  80. if (d) {
  81. while ( (dir = readdir(d)) != NULL ) {
  82. strcpy(strTemp, dir->d_name);
  83. if (strTemp[0] != '.') {
  84. nrOfStrs++;
  85. strcpy(ptrFileLst[nrOfStrs], strTemp);
  86. }
  87. }
  88. closedir(d);
  89. }
  90. for (q = 0; q <= curLstInd; q++) {
  91. indPtrFileAcc = numLst[q];
  92. strcpy(srcFile, srcDir);
  93. strcat(srcFile, "/");
  94. strcat(srcFile, ptrFileLst[indPtrFileAcc]);
  95. strcpy(dstFile, dstDir);
  96. strcat(dstFile, "/");
  97. strcat(dstFile, ptrFileLst[indPtrFileAcc]);
  98. srcFileDesc = open(srcFile, O_RDONLY);
  99. dstFileDesc = creat(dstFile, OUTPUT_MODE);
  100. while(1) {
  101. readByteCount = read(srcFileDesc, buffer, BUF_SIZE);
  102. if (readByteCount <= 0)
  103. break;
  104. writeByteCount = write(dstFileDesc, buffer, readByteCount);
  105. if(writeByteCount <= 0)
  106. exit(4);
  107. }
  108. //close the files
  109. close(srcFileDesc);
  110. close(dstFileDesc);
  111. }
  112. }

这段代码可能是最复杂的:

  1. while(1) {
  2. readByteCount = read(srcFileDesc, buffer, BUF_SIZE);
  3. if (readByteCount <= 0)
  4. break;
  5. writeByteCount = write(dstFileDesc, buffer, readByteCount);
  6. if (writeByteCount <= 0)
  7. exit(4);
  8. }

这将从指定的文件中读取多个字节(readByteCount)到字符缓冲区中。该函数的第一个参数是文件名(srcFileDesc)。第二个参数是一个指向字符缓冲区的指针,这之前在程序中声明过。该函数的最后一个参数是缓冲区的大小。

程序返回读取的字节数(在本例中为 4 个字节)。如果返回的数字为 0 或更少,则第一个 if 子句会跳出循环。

如果读取字节数为 0,则所有写入完成,循环中断以写入下一个文件。如果读取的字节数小于 0,则发生错误并退出程序。

当读取 4 个字节时,它会写入它们。write 函数接受三个参数。第一个是要写入的文件,第二个是字符缓冲区,第三个是要写入的字节数(4 个字节) .该函数返回写入的字节数。

如果写入了 0 个字节,则发生了写入错误,因此第二个 if 子句退出程序。

while 循环读取并复制文件,一次 4 个字节,直到文件被复制。复制完成后,你可以将随机生成的 mp3 文件的目录复制到你的智能手机。

复制和写入例程相当有效,因为它们使用 Linux 中的文件系统调用。

改进代码

该程序很简单,可以在用户界面和灵活性方面进行改进。例如,你可以实现一个计算源目录中文件数量的函数,这样你就不必手动输入它。你可以添加选项,这样你就可以非交互地传递百分比和路径。但是代码做了我需要它做的事情,它是 C 编程语言简单效率的演示。


via: https://opensource.com/article/22/7/c-linux-mp3

作者:Rikard Grossman-Nielsen 选题:lkxed 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出


LCTT 译者 :geekpi
💎💎💎💎
翻译: 1736.5 篇
|
贡献: 3196 天
2013-10-25
2022-07-26
https://linux.cn/lctt/geekpi
欢迎遵照 CC-BY-SA 协议规定转载,
如需转载,请在文章下留言 “转载:公众号名称”,
我们将为您添加白名单,授权“转载文章时可以修改”。

微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
在 Linux 上使用 Rhythbox 听音乐 | Linux 中国又有 Linux 开发者加入微软,这次是 systemd 的创建者 | Linux 中国Plex 桌面播放器现已支持 Linux | Linux 中国在 Linux 中使用 Etcher 创建可启动 USB – 下载和使用指南 | Linux 中国使用 LaTeX 创建优美的 PDF 文件 | Linux 中国如何从 Windows 上用 SSH 连接到 Linux | Linux 中国如何在 Linux 上动态链接模块库 | Linux 中国如何使用 Linux sed 命令自动进行文件编辑 | Linux 中国在 GNOME 中创建你自定义的浅色和深色壁纸 | Linux 中国神秘的 GeckoLinux 创建者推出了一个新的 Debian 合成发行版 | Linux 中国挖郁金香种球面对事业危机和瓶颈值得尝试的六款 Linux 文字处理程序 | Linux 中国关于 Linux 和 Git 的创造者 Linus Torvalds 的 20 件趣事 | Linux 中国如何通过 chroot 恢复 Arch Linux 系统 | Linux 中国Amberol 是一款外观漂亮的 Linux 音乐播放器,只播放音乐,不做其他事情 | Linux 中国如何在 RHEL 9 上创建本地 Yum/DNF 仓库 | Linux 中国如何在 Arch Linux 中安装深度桌面(DDE) | Linux 中国猜图外乡人 - 还好不是杀人狂魔如何在 Ubuntu/Linux 和 Windows 之间共享文件夹 | Linux 中国GNU C 编译器的程序员入门指南 | Linux 中国在 Linux 上使用 Bash 创建一个临时文件 | Linux 中国我是如何使用 Linux fmt 命令来格式化文本 | Linux 中国如何使用 Dockerfile 创建自定义 Docker 镜像 | Linux 中国2700 盘古典CD,丰富了我的收藏!开源朗读者:我是如何帮助妈妈从 Windows 切换至 Linux 的 | Linux 中国如何在基于 Ubuntu 的 Linux 发行版上安装最新的 Vim 9.0 | Linux 中国如何在 Manjaro 和其他 Arch Linux 衍生品上安装 Discord 客户端 | Linux 中国Sunamu:在 Linux 桌面上显示当前播放音乐的歌词 | Linux 中国编写你的第一段 JavaScript 代码 | Linux 中国通过编写“猜数字”游戏来学习 Awk | Linux 中国重新想象和设计你的文件和目录列表 | Linux 中国初级:如何在 Arch Linux 中安装 Yay AUR 助手 | Linux 中国如何在 Linux 中使用 Pandoc 转换文件格式 | Linux 中国
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。