MIME type


The aim of this puzzle is to match files with their MIME type by reading their extensions. It involves without naming it a peculiar data structure : dictionaries. Let us see a simple implementation in C, and how to use standards in Java and Python.

C

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4.  
  5. // Represents an association between an extension, and its mime type
  6. struct pair { char *ext; char *mime; };
  7.  
  8. // A dictionnary can be implented very simply as a pair array
  9. struct dict {
  10. int size;
  11. struct pair *elmts;
  12. };
  13.  
  14. /* Returns the MIME type of label 'ext' in dictionnary 'dict'
  15. or "UNKNOWN" if there is no matching extension */
  16. char *assoc (struct dict *d, char *ext) {
  17. for (int i = 0; i < d->size; i++)
  18. if (strcmp(d->elmts[i].ext, ext) == 0)
  19. return d->elmts[i].mime;
  20. return "UNKNOWN";
  21. }
  22.  
  23. // Replaces all uppercase chars of 'str' by the corresponding lowercase chars
  24. void toLower (char *str) {
  25. for (; *str != '\0'; str++)
  26. *str = tolower(*str);
  27. }
  28.  
  29. // Returns a pointer on the first char of the extension of 'str' if it has one
  30. // or NULL else
  31. char *getExt (char *str) {
  32. for (char *ext = str+strlen(str); ext != str; ext--)
  33. if (*(ext-1) == '.')
  34. return ext;
  35. return NULL;
  36. }
  37.  
  38. int main(int argc, char** argv)
  39. {
  40. int dictSize, nbFiles;
  41. scanf("%d\n%d\n", &dictSize, &nbFiles);
  42.  
  43. // Initializes the dictionary extension-MIME type
  44. struct dict d;
  45. struct pair *p;
  46. d.size = dictSize;
  47. d.elmts = malloc(d.size*sizeof(struct pair));
  48. for (int i = 0; i < dictSize; i++) {
  49. p = d.elmts+i;
  50. p->ext = malloc(11*sizeof(char));
  51. p->mime = malloc(51*sizeof(char));
  52. // here using scanf is quite safe because maximal lengths are known
  53. scanf("%s %s\n", p->ext, p->mime);
  54. toLower(p->ext);
  55. }
  56.  
  57. // processes file 1 by 1, by isolating ext and matching it with a MIME type
  58. char file[257];
  59. char *ext;
  60. for (int i = 0; i < nbFiles; i++) {
  61. gets(file);
  62. toLower(file);
  63. ext = getExt(file);
  64. printf("%s\n", assoc(&d, ext?ext:""));
  65. }
  66.  
  67. for (int i = 0; i < dictSize; i++) {
  68. p = d.elmts+i;
  69. free(p->ext);
  70. free(p->mime);
  71. }
  72. free(d.elmts);
  73.  
  74. return EXIT_SUCCESS;
  75. }

Java

  1. import java.util.*;
  2.  
  3. class Solution {
  4. public static void main(String args[]) {
  5. Scanner in = new Scanner(System.in);
  6.  
  7. int nbAssociations = in.nextInt();
  8. int nbFiles = in.nextInt();
  9. in.nextLine();
  10. // assoc associates to each file extension the corresponding MIME type
  11. Map assoc = new HashMap();
  12. for (int i = 0; i < nbAssociations; i++) {
  13. assoc.put(in.next().toLowerCase(), in.next());
  14. in.nextLine();
  15. }
  16.  
  17. for (int i = 0; i < nbFiles; i++) {
  18. // isolates the extension, which is the part after the last .
  19. String fileName = in.nextLine().toLowerCase();
  20. int pos = fileName.lastIndexOf('.');
  21. String extension = (pos == -1) ? "" : fileName.substring(pos+1, fileName.length());
  22. // prints the corresponding MIME type, or UNKNOWN
  23. System.out.println((String)(assoc.getOrDefault(extension, "UNKNOWN")));
  24. }
  25. }
  26. }

Python 3

  1. import sys
  2.  
  3. nbAssociations, nbFiles = int(input()), int(input())
  4.  
  5. # assoc associates to each file extension the corresponding MIME type
  6. assoc = {}
  7. for i in range(nbAssociations):
  8. ext, mime = input().split()
  9. assoc[ext.lower()] = mime
  10.  
  11. for i in range(nbFiles):
  12. name = input().lower().split('.')
  13. ext = name[-1] if len(name) != 1 else None
  14. print(assoc[ext] if ext in assoc else "UNKNOWN")